package com.saki.qq.wtlogin.pack.send;

import com.saki.encode.Canvart;
import com.saki.encode.Code;
import com.saki.qq.global.Global;
import com.saki.qq.wtlogin.pack.Pack;

public abstract class SendPack {
    public static final byte A = 0x0A;
    public static final byte B = 0x0B;
    Pack pack = new Pack();

    private byte cmdType = A;
    private byte type = 1;
    private byte[] token44;
    private int seq = -1;
    private long uin = Global.qq;
    protected String command;
    private long appsub = -1;
    private boolean dub = true;
    private byte[] token4c;
    protected byte[] msgCookie = new byte[]{0x71, 0x08, 0x3E, (byte) 0xED};
    private String imei;
    private byte[] token14;
    private String version;
    private byte[] key;
    private byte[] publicKey;
    private byte[] cmd;
    private int seqid = -1;

    public SendPack(String command) {
        this.command = command;
    }

    private void encodeContent(byte[] content, byte[] key) {
        content = Code.QQTEAencrypt(content, key);
        pack.appendBytes(content);
        pack.addInHead(Canvart.Int2Bytes(pack.length() + 4));
    }

    protected abstract byte[] getContent();

    public int getSeq() {
        return seq;
    }

    public long getUin() {
        return uin;
    }

    private void packAppSub(long appsub, boolean dub) {
        if (appsub != -1) {
            pack.appendLong(appsub);
            if (dub)
                pack.appendLong(appsub);
            else
                pack.appendLong(-1);
            pack.appendBytes(new byte[]{0x01, 0x00, 0x00, 0x00});
            pack.appendInt(0);
            pack.appendInt(0);
        }
    }

    private void packCMD(byte cmd, byte type) {
        pack.appendByte(0);
        pack.appendByte(0);
        pack.appendByte(0);
        pack.appendByte(cmd);
        pack.appendByte(type);
    }

    private void packCommand(String cmd) {
        pack.appendInt(cmd.length() + 4);
        pack.appendString(cmd);
    }

    protected void packContent() {
        packContent(uin, cmd, key, publicKey, getContent());
    }

    public void packContent(long qq, byte[] cmd, byte[] key, byte[] publicKey,
                            byte[] bin) {
        if (cmd == null || key == null || publicKey == null) {
            pack.appendInt(bin.length + 4);
            pack.appendBytes(bin);
        } else {
            Pack body = new Pack();
            body.appendBytes(new byte[]{0x1F, 0x41});
            body.appendBytes(cmd);
            body.appendBytes(new byte[]{0x00, 0x01});
            body.appendLong(qq);
            body.appendBytes(new byte[]{0x03, 0x07, 0x00, 0x00, 0x00, 0x00,
                    0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
                    0x01});
            body.appendBytes(key);
            body.appendBytes(new byte[]{0x01, 0x02});
            body.appendShort(publicKey.length);
            body.appendBytes(publicKey);
            //
            body.appendBytes(bin);
            body.addInHead(Canvart.Short2Bytes((short) (body.getAll().length + 4)));
            body.addInHead((byte) 0x02);
            body.addInHead(Canvart.Int2Bytes(body.getAll().length + 5));
            body.appendByte(3);
            pack.appendBytes(body.getAll());
        }
    }

    protected void packHead() {
        byte[] bin = pack.getAll();
        pack.clear();
        packCMD(cmdType, type);
        packToken44(token44, seq);
        packUin(uin == -1 ? null : String.valueOf(uin));
        encodeContent(bin, UsedKey());
    }

    private void packImei(String imei) {
        if (imei != null) {
            pack.appendInt(imei.length() + 4);
            pack.appendString(imei);
        }
    }

    protected void packInfo() {
        packRequestionId(seqid);
        packAppSub(appsub, dub);
        packToken4c(token4c);
        packCommand(command);
        packMsgCookie(msgCookie);
        packITV(imei, token14, version);
        pack.appendInt(4);// 未知数据位置

        pack.addInHead(Canvart.Int2Bytes(pack.length() + 4));
        packContent();
    }

    private void packITV(String imei, byte[] token14, String version) {
        if (imei != null && version != null) {
            packImei(imei);
            packToken14(token14);
            packVersion(version);
        }
    }

    private void packMsgCookie(byte[] msgCookie) {
        if (msgCookie != null) {
            pack.appendInt(msgCookie.length + 4);
            pack.appendBytes(msgCookie);
        } else {
            pack.appendInt(4);
        }
    }

    private void packRequestionId(int seq) {
        if (seq != -1)
            pack.appendInt(seq);
    }

    private void packToken14(byte[] token14) {
        if (token14 != null) {
            pack.appendInt(token14.length + 4);
            pack.appendBytes(token14);
        } else {
            pack.appendInt(4);
        }
    }

    private void packToken44(byte[] token44, int seq) {
        if (token44 != null) {
            pack.appendInt(token44.length + 4);
            pack.appendBytes(token44);
        } else if (seq != -1) {
            pack.appendInt(seq);
        } else {
            pack.appendInt(4);
        }
    }

    protected void packToken4c(byte[] token4c) {
        if (token4c != null) {
            pack.appendInt(token4c.length + 4);
            pack.appendBytes(token4c);
        } else {
            pack.appendInt(4);
        }
    }

    private void packUin(String uin) {
        pack.appendByte(0);
        if (uin == null) {
            pack.appendByte(0);
            pack.appendInt(1328);
        } else {
            pack.appendInt(uin.length() + 4);
            pack.appendString(uin);
        }
    }

    private void packVersion(String version) {
        if (version != null) {
            pack.appendShort(version.length() + 2);
            pack.appendString(version);
        }
    }

    public void setAppsub(long appsub) {
        this.appsub = appsub;
    }

    public void setAppsub(long appsub, boolean dub) {
        this.appsub = appsub;
        this.dub = dub;
    }

    public void setCmd(byte[] cmd) {
        this.cmd = cmd;
    }

    public void setCommand(String command) {
        this.command = command;
    }

    public void setImei(String imei) {
        this.imei = imei;
    }

    public void setKey(byte[] key) {
        this.key = key;
    }

    public void setMsgCookie(byte[] msgCookie) {
        this.msgCookie = msgCookie;
    }

    public void setMsgType(byte cmdType) {
        this.cmdType = cmdType;
    }

    public void setPublicKey(byte[] publicKey) {
        this.publicKey = publicKey;
    }

    public void setRequestId(int seqid) {
        this.seqid = seqid;
    }

    public void setSeq(int seq) {
        this.seq = seq;
    }

    public void setToken14(byte[] token14) {
        this.token14 = token14;
    }

    public void setToken44(byte[] token44) {
        this.token44 = token44;
    }

    public void setToken4c(byte[] token4c) {
        this.token4c = token4c;
    }

    public void setType(int i) {
        this.type = (byte) i;
    }

    public void setUin(long uin) {
        this.uin = uin;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    public byte[] toByteArray() {
        if (pack.isEmpty()) {
            packInfo();
            packHead();
        }
        return pack.getAll();
    }

    protected abstract byte[] UsedKey();

}
