
var { Socket } = require('net');
var WhoisConfig = require('./whois.servers.json');
require('./prototype');


var Search = function ({ host, domain, port = 43, timeout = 10000 }) {
    const socket = new Socket();
    return new Promise((resolve, reject) => {
        socket.connect(port, host, () => { });
        var stdout = ""
        var stderr = ""
        socket
            .on("connect", function () {
                socket.write(Buffer.from(`${domain}\r\n`))
            })
            .on("data", function (chunk) {
                stdout += chunk.toString();
            })
            .on('error', function (error) {
                stderr = error;
            })
            .on('end', function () {
                socket.destroy();
            })
            .on('close', function () {
                if (stderr) reject(stderr)
                else resolve({ stdout, stderr })
            });
        socket.setTimeout(timeout, () => {
            socket.destroy();
        });
    })
};

var Format = function (stdout) {
    var ResultMap = {}
    var ExpiredDate = ""
    var Registrar = "";
    try {
        var lines = stdout
            .replace(/(\r)/g, '')
            .split('\n')
            .filter(row => !row.startsWith("%") && row != "" && row.indexOf(':') != -1)
        lines
            .map(row => row.split(':'))
            .map(function ([key, value, ...args]) {
                key = key.trim().replace(/\ /g, '_')
                value = value.trim()
                if (args.length > 0) {
                    value = value + ':' + args.join(':')
                }
                ResultMap[key] = value;
                if (key.toLowerCase().indexOf('expir') >= 0) {
                    var dt = new Date(value)
                    if (!isNaN(dt.getFullYear())) {
                        ExpiredDate = value
                    }
                }
                if (["registrant", "registrar"].includes(key.toLowerCase())) {
                    Registrar = value
                }
            })
    } catch (error) {
        throw error
    }
    if (ExpiredDate == "" && ResultMap.Registered) {
        ExpiredDate = ResultMap.Registered
        ExpiredDate = new Date(ExpiredDate)
        if (!isNaN(ExpiredDate.getFullYear())) {
            ExpiredDate = ExpiredDate.getTime()
            while (ExpiredDate < Date.now()) {
                ExpiredDate = new Date(ExpiredDate)
                ExpiredDate = ExpiredDate.setFullYear(ExpiredDate.getFullYear() + 1)
            }
            ExpiredDate = new Date(ExpiredDate).toLocaleString()
        }
    }
    var Days = 0
    if (ExpiredDate) {
        ExpiredDate = new Date(ExpiredDate)
        var ExpiredTime = ExpiredDate.getTime() - Date.now();
        Days = Math.floor(ExpiredTime / 86400000)
        ExpiredDate = ExpiredDate.Format('yyyy-MM-dd HH:mm')

    }
    return { ResultMap, ExpiredDate, Days, Registrar, };
};


module.exports = async function (domain) {
    var tld = domain.split('.').slice(1).join('.')
    var whoisServers = WhoisConfig[tld]
    var result
    for (let host of whoisServers) {
        try {
            let { stdout, stderr } = await Search({ host, domain })
            if (stderr) {
                stderr = stderr.stack || stderr
            }
            stderr = stderr;
            var format = Format(stdout)
            result = { stdout, stderr, format }
            break;
        } catch (error) {

        }
    }
    return result
}

