/*
 * This file is a part of the SteamWar software.
 *
 * Copyright (C) 2022  SteamWar.de-Serverteam
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

package de.steamwar.velocitycore.network.handlers;

import de.steamwar.network.packets.PacketHandler;
import de.steamwar.network.packets.common.FightEndsPacket;
import de.steamwar.sql.SchemElo;
import de.steamwar.sql.SchematicNode;
import de.steamwar.sql.SchematicType;
import de.steamwar.velocitycore.ArenaMode;

public class EloSchemHandler extends PacketHandler {

    private static final int K = 20;

    public static boolean publicVsPrivate(FightEndsPacket packet) {
        if (packet.getRedSchem() == -1 && packet.getBlueSchem() == -1) {
            return false;
        }
        SchematicNode blueSchem = SchematicNode.getSchematicNode(packet.getBlueSchem());
        SchematicNode redSchem = SchematicNode.getSchematicNode(packet.getRedSchem());
        return (blueSchem.getOwner() == 0) != (redSchem.getOwner() == 0);
    }

    @Handler
    public void handle(FightEndsPacket fightEndsPacket) {
        SchematicType type = SchematicType.fromDB(fightEndsPacket.getGameMode());
        if (type == null) return;
        ArenaMode arenaMode = ArenaMode.getBySchemType(type);
        if (!arenaMode.isRanked()) return;

        if (publicVsPrivate(fightEndsPacket))
            return;

        calcSchemElo(fightEndsPacket);
    }

    private void calcSchemElo(FightEndsPacket fightEndsPacket) {
        double blueResult;
        if (fightEndsPacket.getWin() == 0) {
            blueResult = 0.5;
        } else if (fightEndsPacket.getWin() == 1) {
            blueResult = 1;
        } else {
            blueResult = 0;
        }

        int blueSchemElo = SchemElo.getCurrentElo(fightEndsPacket.getBlueSchem());
        int redSchemElo = SchemElo.getCurrentElo(fightEndsPacket.getRedSchem());
        calcSchemElo(redSchemElo, blueSchemElo, fightEndsPacket.getRedSchem(), blueResult);
        calcSchemElo(blueSchemElo, redSchemElo, fightEndsPacket.getBlueSchem(), 1 - blueResult);
    }

    private void calcSchemElo(int eloSchemOwn, int eloSchemEnemy, int schemId, double result) {
        double winSchemExpectation = calcWinExpectation(eloSchemOwn, eloSchemEnemy);
        SchemElo.setElo(schemId, (int) Math.round(eloSchemOwn + K * (result - winSchemExpectation)));
    }

    private double calcWinExpectation(int eloOwn, int eloEnemy) {
        return 1 / (1 + Math.pow(10, (eloEnemy - eloOwn) / 600f));
    }
}
