package com.alterdekim.hearthhack.component.processor;


import com.alterdekim.Protocol;
import com.alterdekim.hearthhack.component.TcpConnection;
import com.alterdekim.hearthhack.util.BattleNetPacket;
import com.alterdekim.hearthhack.util.Util;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.StandardCharsets;

@Slf4j
public class AuthProcessor extends Processor {

    public AuthProcessor() {
        this.setProcessorId(1);
    }

    private void logonRequest(BattleNetPacket packet, TcpConnection conn ) throws Exception {
        // Protocol.LogonRequest lr = Protocol.LogonRequest.parseFrom(packet.getBody());
        Protocol.Header h = Processor.generateResponse(0, packet.getHeader().getToken(), 0, 0);

        conn.send(new BattleNetPacket(h, new byte[0]));

        byte[] b = Util.hexStringToByteArray("080110C383A8F4CEBDCC021800");

        h = Protocol.Header.newBuilder()
                .setServiceId(1)
                .setObjectId(0)
                .setToken(conn.nextToken())
                .setMethodId(12)
                .setStatus(0)
                .setSize(b.length)
                .build();
        conn.send(new BattleNetPacket(h, b));
        
        h = Protocol.Header.newBuilder()
                .setServiceId(1)
                .setObjectId(0)
                .setToken(conn.nextToken())
                .setMethodId(13)
                .setStatus(0)
                .setSize(0)
                .build();

        conn.send(new BattleNetPacket(h, new byte[0]));
        
        //120C7765625F617574685F75726C1A16687474703A2F2F68732F6C6F67696E2F7A2E68746D6C
        byte[] us = "http://0.0.0.0:8080".getBytes(StandardCharsets.UTF_8);
        byte[] bb = Util.hexStringToByteArray("120C7765625F617574685F75726C1A"+Util.intToHex(us.length)+Util.bytesToHex(us));

        h = Protocol.Header.newBuilder()
                .setServiceId(8)
                .setObjectId(0)
                .setToken(conn.nextToken())
                .setMethodId(3)
                .setStatus(0)
                .setSize(bb.length)
                .build();

        conn.send(new BattleNetPacket(h, bb));
        
    }

    private void selectGameAccount(BattleNetPacket packet, TcpConnection conn) throws Exception {
        Protocol.Header nnh = Processor.generateResponse(0, packet.getHeader().getToken(), 0, 0);
        conn.send(new BattleNetPacket(nnh, new byte[0]));
    }

    private void verifyWebCredentials(BattleNetPacket packet, TcpConnection conn) throws Exception {
        Protocol.VerifyWebCredentialsRequest verifyWebCredentialsRequest
                = Protocol.VerifyWebCredentialsRequest.parseFrom(packet.getBody());

        String token = new String( verifyWebCredentialsRequest.getWebCredentials().toByteArray() );

        if( !conn.getUserService().authMe(token) ) { conn.stopListeningAndDisconnect(); return; }
        conn.setUserId(conn.getUserService().extractId(token));
        Protocol.Header h = Processor.generateResponse(0, packet.getHeader().getToken(), 0, 0);

        conn.send(new BattleNetPacket(h, new byte[0]));

        h = Protocol.Header.newBuilder()
                .setServiceId(10)
                .setMethodId(1)
                .setToken(conn.nextToken())
                .setObjectId(0)
                .setSize(2)
                .setStatus(0)
                .build();

        conn.send(new BattleNetPacket(h, Util.hexStringToByteArray("0800")));
        
        h = Protocol.Header.newBuilder()
                .setServiceId(10)
                .setMethodId(1)
                .setToken(conn.nextToken())
                .setObjectId(0)
                .setSize(2)
                .setStatus(0)
                .build();

        conn.send(new BattleNetPacket(h, Util.hexStringToByteArray("0800")));

        Protocol.LogonResult logonResult = Protocol.LogonResult.newBuilder()
                .setErrorCode(0)
                .setAccount(Protocol.EntityId.newBuilder().setHigh(72057594037927936L).setLow(437154195L).build())
                .addGameAccount(Protocol.EntityId.newBuilder().setHigh(144115198130930503L).setLow(78330215L).build())
                .setEmail("")
                .addAvailableRegion(1)
                .addAvailableRegion(2)
                .addAvailableRegion(3)
                .addAvailableRegion(6)
                .addAvailableRegion(98)
                .setConnectedRegion(2)
                .setBattleTag(conn.getUserService().findById(conn.getUserId()).getDisplayName()+"#66666")
                .setGeoipCountry("SK")
                .build();

        h = Protocol.Header.newBuilder()
                .setServiceId(1)
                .setMethodId(5)
                .setToken(conn.nextToken())
                .setObjectId(0)
                .setSize(logonResult.getSerializedSize())
                .setStatus(0)
                .build();

        conn.send(new BattleNetPacket(h, logonResult.toByteArray()));
        
    }

    @Override
    public void process(BattleNetPacket packet, TcpConnection conn) throws Exception {
        switch (packet.getHeader().getMethodId()) {
            case 1 -> logonRequest(packet, conn);
            case 4 -> selectGameAccount(packet, conn);
            case 7 -> verifyWebCredentials(packet, conn);
            default -> log.error("Can't process weird AuthProcessor method: {}", packet.getHeader().getMethodId());
        }
    }

    @Override
    public String getExportName() {
        return "bnet.protocol.authentication.AuthenticationClient";
    }
}
