import * as path from "path";
import { Data } from "../basetypes/Data";
import { AuthType } from "../enums/AuthType";
import { ConnectionType } from "../enums/ConnectionType";
import { MessageHeader } from "../smime/MessageHeader";
import { DataNativeBinding, MessageHeaderNativeBinding, POPMessageInfoNativeBinding, POPSessionNativeBinding } from '../types';
import { NodeTrustedMailcore2NativeBinding } from "../types/NodeTrustedMailcore2NativeBinding";
import { POPMessageInfo } from "./POPMessageInfo";

// tslint:disable-next-line: no-var-requires
let bindings: NodeTrustedMailcore2NativeBinding;
try {
    bindings = require(path.join(__dirname, "../../lib/binding/trusted_mailcore2.node"));
} catch(e) {
    bindings = require(path.join(__dirname, "../../lib/binding/trusted_mailcore2_no_crypto.node"));
}

// tslint:disable-next-line
const { POPSession: _POPSession } = bindings;

/**
 * POPSession Class
 *
 * @public
 */
class POPSession extends bindings.POPSession {
    protected handle: POPSessionNativeBinding;

    constructor() {
        super();

        const handle = new _POPSession();
        this.handle = handle;
    }

    /**
     * Set hostname
     *
     * @memberof POPSession
     */
    set hostname(hostname: string) {
        this.handle.hostname = hostname;
    }

    /**
     * Get hostname
     *
     * @type {string}
     * @memberof POPSession
     */
    get hostname(): string {
        return this.handle.hostname;
    }

    /**
     * Set port
     *
     * @memberof POPSession
     */
    set port(port: number) {
        this.handle.port = port;
    }

    /**
     * Get port
     *
     * @type {number}
     * @memberof POPSession
     */
    get port(): number {
        return this.handle.port;
    }

    /**
     * Set string
     *
     * @memberof POPSession
     */
    set username(username: string) {
        this.handle.username = username;
    }

    /**
     * Get string
     *
     * @type {string}
     * @memberof POPSession
     */
    get username(): string {
        return this.handle.username;
    }

    /**
     * Set password
     *
     * @memberof POPSession
     */
    set password(password: string) {
        this.handle.password = password;
    }

    /**
     * Get password
     *
     * @type {string}
     * @memberof POPSession
     */
    get password(): string {
        return this.handle.password;
    }

    /**
     * Set checkCertificateEnabled
     *
     * @memberof POPSession
     */
    set checkCertificateEnabled(isEnabled: boolean) {
        this.handle.checkCertificateEnabled = isEnabled;
    }

    /**
     * Get checkCertificateEnabled
     *
     * @type {boolean}
     * @memberof POPSession
     */
    get checkCertificateEnabled(): boolean {
        return this.handle.checkCertificateEnabled;
    }

    /**
     * Set authType
     *
     * @memberof POPSession
     */
    set authType(authType: AuthType) {
        this.handle.authType = authType;
    }

    /**
     * Get authType
     *
     * @type {AuthType}
     * @memberof POPSession
     */
    get authType(): AuthType {
        return this.handle.authType;
    }

    /**
     * Set connectionType
     *
     * @memberof POPSession
     */
    set connectionType(connectionType: ConnectionType) {
        this.handle.connectionType = connectionType;
    }

    /**
     * Get connectionType
     *
     * @type {ConnectionType}
     * @memberof POPSession
     */
    get connectionType(): ConnectionType {
        return this.handle.connectionType;
    }

    /**
     * Set timeout
     *
     * @memberof POPSession
     */
    set timeout(timeoutValue: number) {
        this.handle.timeout = timeoutValue;
    }

    /**
     * Get timeout
     *
     * @type {number}
     * @memberof POPSession
     */
    get timeout(): number {
        return this.handle.timeout;
    }

    /**
     * Set strictGost flag (to force using GOST for TLS)
     *
     * @memberof IMAPSession
     */
    set strictGost(value: Boolean) {
        this.handle.strictGost = value;
    }

    /**
     * Get strictGost flag (to force using GOST for TLS)
     *
     * @type {Boolean}
     * @memberof IMAPSession
     */
    get strictGost(): Boolean {
        return this.handle.strictGost;
    }

    /**
     * Validate exist account
     *
     * @returns {number} 0 - success, other - failure
     *
     * @memberof POPSession
     */
    public async checkAccount(): Promise<number> {
        return this.handle.checkAccount();
    }

    /**
     * Connect
     *
     * @return {number} returns error code
     * @memberof POPSession
     */
    public connect(): number {
        return this.handle.connect();
    }

    /**
     * Disconnect connection
     *
     * @memberof POPSession
     */
    public disconnect(): void {
        this.handle.disconnect();
    }


    /**
     * Login if needed to session
     *
     * @return {*}  {number}
     * @memberof POPSession
     */
    public login(): number {
        return this.handle.login();
    }

    /**
     * Fetch message info for all messages
     *
     * @return {*}  {POPMessageInfo[]} array of all messages info
     * @memberof POPSession
     */
    public fetchMessages(): POPMessageInfo[] {
        const msgsInfos: POPMessageInfoNativeBinding[] = this.handle.fetchMessages();

        const result: POPMessageInfo[] = [];
        for (let curInfo of msgsInfos) {
            const value = new POPMessageInfo();
            value.handle = curInfo;
            result.push(value);
        }
        return result;
    }

    /**
     * Fetch message header by index or message info
     *
     * @param {number | POPMessageInfo} msg message index or info to fetch header
     * @return {*}  {MessageHeader}
     * @memberof POPSession
     */
    public fetchHeader(msg: number | POPMessageInfo): MessageHeader {
        const msgHdr: MessageHeaderNativeBinding =
            (typeof msg === "number")
                ? this.handle.fetchHeader(msg)
                : this.handle.fetchHeader(msg.handle);

        const value = new MessageHeader();
        value.handle = msgHdr;
        return value;
    }

    /**
     * Fetch message data by index or info
     *
     * @param {number} index Index or info of message to fetch header
     * @return {*}  {Data}
     * @memberof POPSession
     */
    public fetchMessage(msg: number | POPMessageInfo): Data {
        const msgData: DataNativeBinding =
            (typeof msg === "number")
                ? this.handle.fetchMessage(msg)
                : this.handle.fetchMessage(msg.handle);

        const value = new Data();
        value.handle = msgData;
        return value;
    }

    /**
     * Delets message by index or message info
     *
     * @param {number} index Index or info of message to fetch header
     * @return {*}  {Data}
     * @memberof POPSession
     */
    public deleteMessage(msg: number | POPMessageInfo): number {
        if ((typeof msg === "number")) {
            return this.handle.deleteMessage(msg);
        }

        return this.handle.deleteMessage(msg.handle);

    }

    /**
     * noop
     *
     * @return {*}  {number} error code
     * @memberof POPSession
     */
    noop(): number {
        return this.handle.noop();
    }
}

export { POPSession };

