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.GameType;
import com.alterdekim.hearthhack.util.Util;
import com.google.protobuf.ByteString;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.StandardCharsets;

import static com.alterdekim.hearthhack.util.GameUtilities.generateSmallNotification;

@Slf4j
public class GameMasterProcessor extends Processor {

    public GameMasterProcessor() {
        this.setProcessorId(8);
    }

    private void processFindGame(BattleNetPacket packet, TcpConnection conn) throws Exception {
        // FindGameRequest FindGameResponse game_master
        // GameType
        Protocol.FindGameRequest gameRequest = Protocol.FindGameRequest.parseFrom(packet.getBody());

        Protocol.Attribute a = gameRequest.getProperties().getCreationAttributesList().stream()
                .filter(p -> p.hasName() && p.getName().equals("type"))
                .findFirst()
                .get();
        GameType gameType = GameType.parseFromInt((int) a.getValue().getIntValue());
        if( gameType != GameType.GT_CASUAL ) return;
        Protocol.FindGameResponse response = Protocol.FindGameResponse.newBuilder()
                .setQueued(true)
                .build();

        Protocol.Header header = Processor.generateResponse(response.getSerializedSize(), packet.getHeader().getToken(), 0, 0);
        conn.send(new BattleNetPacket(header, response.toByteArray()));


        Protocol.GameFoundNotification notification = Protocol.GameFoundNotification.newBuilder()
                .setRequestId(gameRequest.getRequestId())
                //.setGameHandle(Protocol.GameHandle.newBuilder().setFactoryId(gameRequest.getFactoryId()))
                .addConnectInfo(Protocol.ConnectInfo.newBuilder()
                        .setHost("localhost")
                        .setPort(1119)
                        .setMemberId(Protocol.EntityId.newBuilder()
                                .setHigh(72057594037927936L)
                                .setLow(437154195L))
                ).build();

        // method_id = 1
        // service = 3

        header = Protocol.Header.newBuilder()
                .setServiceId(3)
                .setMethodId(1)
                .setSize(notification.getSerializedSize())
                .setToken(conn.nextToken())
                .setObjectId(0)
                .setStatus(0)
                .build();

        conn.send(new BattleNetPacket(header, notification.toByteArray()));


   /*     byte[] ip = "localhost".getBytes(StandardCharsets.US_ASCII);
        log.info("ip: {} lenhex: {}, len: {}", Util.bytesToHex(ip), Util.intToHex(ip.length), ip.length);
        byte[] bb = Util.hexStringToByteArray("0A120900000000000000021100000000000000001212094743545702000002116739AB04000000001A08475F524553554C54221E0A0F67616D655F726571756573745F6964120B48B6D2A3C7A4FCA2E1B901220B0A056572726F7212024800222E0A0B67616D655F68616E646C65121F3A1D09F64263F5D33456C7121209EEA60D5703000006118C270B000A62A3AB22B3010A0F636F6E6E656374696F6E5F696E666F129F013A9C010A12094743545702000002116739AB040000000012"+Util.intToHex(ip.length)+Util.bytesToHex(ip)+"188C1D2206456A634465492A130A0776657273696F6E12082A0665694B3271762A0D0A0467616D65120518AA80C4062A0C0A06706C61796572120218012A0B0A026964120518B2B0AA1C2A0F0A09726573756D61626C65120210012A1E0A12737065637461746F725F70617373776F726412082A066F44697049664A0A0895A56710E9E6ACB90552150A050D93710E1A120C0D6739AB0415474354571802");

        header = Protocol.Header.newBuilder()
                .setServiceId(4)
                .setMethodId(1)
                .setSize(bb.length)
                .setToken(conn.nextToken())
                .setObjectId(0)
                .setStatus(0)
                .build();

        conn.send(new BattleNetPacket(header, bb));

        Protocol.Notification n = Protocol.Notification.parseFrom(bb);
        Protocol.ConnectInfo ci = Protocol.ConnectInfo.parseFrom(
                n.getAttributeList().stream().filter(p -> p.hasName() && p.getName().equals("connection_info")).findFirst().get().getValue().getMessageValue()
        );
        log.info("GGGG: {}", ci);*/

        Protocol.Notification n1 = Protocol.Notification.newBuilder()
                .setType("G_RESULT")
                .setSenderId(Protocol.EntityId.newBuilder()
                        .setLow(0)
                        .setHigh(144115188075855872L))
                .setTargetId(Protocol.EntityId.newBuilder()
                        .setLow(78330215L)
                        .setHigh(144115198130930503L))
                .addAttribute(Protocol.Attribute.newBuilder()
                        .setName("game_request_id")
                        .setValue(
                                Protocol.Variant.newBuilder()
                                        .setUintValue(1338541484650062879L * 10L)
                        )
                )
                .addAttribute(Protocol.Attribute.newBuilder()
                        .setName("game_handle")
                        .setValue(
                                Protocol.Variant.newBuilder()
                                        .setMessageValue(
                                            Protocol.GameHandle.newBuilder()
                                                    .setFactoryId( (143637261465044426L * 100L) + 14L )
                                                    .setGameId(Protocol.EntityId.newBuilder()
                                                            .setHigh(432345578572981998L)
                                                            .setLow((123678367967794400L * 100L) + 12L))
                                                    .build()
                                                    .toByteString()
                                        )
                        )
                )
                .addAttribute(Protocol.Attribute.newBuilder()
                        .setName("connection_info")
                        .setValue(
                                Protocol.Variant.newBuilder()
                                        .setMessageValue(
                                            Protocol.ConnectInfo.newBuilder()
                                                    .setMemberId(Protocol.EntityId.newBuilder()
                                                            .setHigh(144115198130930503L)
                                                            .setLow(78330215L)
                                                    )
                                                    .setHost("192.168.0.9")
                                                    .setPort(3724)
                                                    .setToken(ByteString.copyFromUtf8("EjcDeI"))
                                                    .addAttribute(Protocol.Attribute
                                                            .newBuilder()
                                                            .setName("version")
                                                            .setValue(Protocol.Variant.newBuilder().setStringValue("eiK2qv")))
                                                    .addAttribute(Protocol.Attribute
                                                            .newBuilder()
                                                            .setName("game")
                                                            .setValue(Protocol.Variant.newBuilder().setIntValue(13697066L)))
                                                    .addAttribute(Protocol.Attribute
                                                            .newBuilder()
                                                            .setName("player")
                                                            .setValue(Protocol.Variant.newBuilder().setIntValue(1L)))
                                                    .addAttribute(Protocol.Attribute
                                                            .newBuilder()
                                                            .setName("id")
                                                            .setValue(Protocol.Variant.newBuilder().setIntValue(59414578L)))
                                                    .addAttribute(Protocol.Attribute
                                                            .newBuilder()
                                                            .setName("resumable")
                                                            .setValue(Protocol.Variant.newBuilder().setBoolValue(true)))
                                                    .addAttribute(Protocol.Attribute
                                                            .newBuilder()
                                                            .setName("spectator_password")
                                                            .setValue(Protocol.Variant.newBuilder().setStringValue("oDipIf")))
                                                    .build().toByteString()
                                        )
                        )
                )
                .addAttribute(Protocol.Attribute.newBuilder()
                        .setName("error")
                        .setValue(
                                Protocol.Variant.newBuilder()
                                        .setUintValue(0)
                        )
                ).build();

        header = Protocol.Header.newBuilder()
                .setServiceId(4)
                .setMethodId(1)
                .setSize(n1.getSerializedSize())
                .setToken(conn.nextToken())
                .setObjectId(0)
                .setStatus(0)
                .build();

        conn.send(new BattleNetPacket(header, n1.toByteArray()));
    }

    @Override
    public void process(BattleNetPacket packet, TcpConnection conn) throws Exception {
        switch(packet.getHeader().getMethodId()) {
            case 3 -> processFindGame(packet, conn);
            default -> log.info("Weird method id: {}", packet.getHeader().getMethodId());
        }
    }

    @Override
    public String getExportName() {
        return "bnet.protocol.channel_invitation.ChannelInvitationService";
    }
}
