package com.jscape.inet.ssh.protocol.v2.marshaling;

import com.jscape.inet.ssh.protocol.messages.IdentificationString;
import com.jscape.inet.ssh.protocol.v2.marshaling.algorithms.Algorithms;
import com.jscape.inet.ssh.protocol.v2.marshaling.algorithms.Compression;
import com.jscape.inet.ssh.protocol.v2.marshaling.algorithms.Encryption;
import com.jscape.inet.ssh.protocol.v2.marshaling.algorithms.Mac;
import com.jscape.inet.ssh.protocol.v2.messages.SshMsgKexInit;

import static com.jscape.util.Parameters.assertNotNull;

/**
 * @author Alex Usun
 */
public class Session {

    public final MessageCodec messageCodec;
    public final PacketCodec packetCodec;
    public final IdentificationString clientIdentificationString;
    public final IdentificationString serverIdentificationString;
    public SshMsgKexInit clientKexInitMessage;
    public SshMsgKexInit serverKexInitMessage;
    public Algorithms algorithms;
    public byte[] sessionId;

    public Session(MessageCodec messageCodec,
                   IdentificationString clientIdentificationString,
                   IdentificationString serverIdentificationString) {
        assertNotNull(messageCodec);
        this.messageCodec = messageCodec;

        this.packetCodec = new PacketCodec(this.messageCodec);

        assertNotNull(clientIdentificationString);
        this.clientIdentificationString = clientIdentificationString;

        assertNotNull(serverIdentificationString);
        this.serverIdentificationString = serverIdentificationString;
    }

    public void initSessionId(byte[] exchangeHash) {
        if (this.sessionId == null) {
            this.sessionId = exchangeHash;
        }
    }

    public void initAlgorithms()
            throws Exception {
        this.algorithms = Algorithms.algorithmsFor(this.clientKexInitMessage, this.serverKexInitMessage);
    }

    public void readingAlgorithms(Encryption encryption, Mac mac, Compression compression) {
        this.packetCodec.readingEncryption(encryption);
        this.packetCodec.readingMac(mac);
        this.packetCodec.readingCompression(compression);
    }

    public void writingAlgorithms(Encryption encryption, Mac mac, Compression compression) {
        this.packetCodec.writingEncryption(encryption);
        this.packetCodec.writingMac(mac);
        this.packetCodec.writingCompression(compression);
    }
}
