import * as path from "path";

import { AuthType } from "../enums/AuthType";
import { ConnectionType } from "../enums/ConnectionType";
import { DsnNotify } from "../enums/DsnNotify";
import { ISMTPAsyncSessionNativeBinding } from '../types';
import { NodeTrustedMailcore2NativeBinding } from "../types/NodeTrustedMailcore2NativeBinding";

// 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 { ISMTPAsyncSession: _ISMTPAsyncSession } = bindings;

/**
 * ISMTPAsyncSession Class
 *
 * @public
 */
class SMTPAsyncSession extends bindings.ISMTPAsyncSession {
    protected handle: ISMTPAsyncSessionNativeBinding;

    constructor() {
        super()

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    /**
     * 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
     *
     * @param {string} from address
     * @returns {number} 0 - success, other - failure
     *
     * @memberof SMTPAsyncSession
     */
    public async checkAccount(from: string): Promise<number> {
        return this.handle.checkAccount(from);
    }

    /**
     * Send message to smtp server
     *
     * @param {string | Buffer} message message
     * @returns {number} error code. 0 - success, other - failure
     *
     * @memberof SMTPAsyncSession
     */
    public async sendMessage(message: string | Buffer, from?: string, recipients?: string[]): Promise<number> {
        return this.handle.sendMessage(message, from, recipients);
    }

    /**
     * Send message to smtp server
     *
     * @param {string} from address
     * @param {string[]} recipients recipients
     * @param {string | Buffer} message message body
     * @param {*} [notify=DsnNotify.DsnNotifyNone] DSN_NOTIFY. Default disabled
     * @returns {number} error code. 0 - success, other - failure
     *
     * @memberof SMTPAsyncSession
     */
    public async sendMessageOperation(from: string, recipients: string[], message: string | Buffer, notify = DsnNotify.DsnNotifyNone): Promise<number> {
        return new Promise<number>((resolve, reject) => {
            this.handle.sendMessageOperation(from, recipients, message, notify, (error, result) => {
                if (error) {
                    reject(error);
                }
                resolve(result);
            });
        });
    }

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

    /**
     * Validate connection status
     *
     * @returns {boolean}
     *
     * @memberof SMTPAsyncSession
     */
    public isDisconnected(): boolean {
        return this.handle.isDisconnected();
    }
}

export { SMTPAsyncSession };
