<?php

namespace ModulesGarden\ProxmoxAddon\App\Libs\Api\OpenSRS;

use ModulesGarden\ProxmoxAddon\Core\Helper;

class FastLookup
{
    private $_socket = false;
    private $_socketErrorNum = false;
    private $_socketErrorMsg = false;
    private $_socketTimeout = 120;
    private $dataObject;
    private $dataFormat;

    public function checkDomain($domain)
    {
        if (!$this->init_socket())
        {
            throw new APIException('oSRS Error - Unable to establish socket: (' . $this->_socketErrorNum . ') ' . $this->_socketErrorMsg);
        }

        $callCheck  = 'check_domain ' . $domain;
        $callLength = strlen($callCheck);
        fputs($this->_socket, $callCheck, $callLength);

        $result = fread($this->_socket, 1024);
        $data   = $this->parseResult($result);

        // Close the socket
        $this->close_socket();

        return $data;
    }

    private function init_socket()
    {
        $register      = Helper\sl('register');
        $this->_socket = pfsockopen($register->registry('OSRS_HOST'), $register->registry('OSRS_FASTLOOKUP_PORT'), $this->_socketErrorNum, $this->_socketErrorMsg, $this->_socketTimeout);
        if (!$this->_socket)
        {
            return false;
        }
        else
        {
            return true;
        }
    }

    private function parseResult($resString)
    {
        if ($resString != '')
        {
            $temArra = explode(' ', $resString);
            if ($temArra[0] == 210)
            {
                $resultReturn = 'Available';
            }
            elseif ($temArra[0] == 211)
            {
                $resultReturn = 'Taken';
            }
            elseif ($temArra[0] == 701)
            {
                $resultReturn = 'Unknown TLD';
            }
            else
            {
                $resultReturn = 'Syntax error - ' . $temArra[0];
            }
        }
        else
        {
            $resultReturn = 'Read error';
        }

        return $resultReturn | '';
    }

    private function close_socket()
    {
        fclose($this->_socket);
        $this->_socket = false;
    }

    public function send($tlds = [])
    {
        $result = $this->checkDomainBunch($this->getDomain(), $tlds);

        $this->resultFullRaw       = $result;
        $this->resultRaw           = $result;
        $this->resultFullFormatted = $this->convertArray2Formatted($this->_formatHolder, $this->resultFullRaw);
        $this->resultFormatted     = $this->convertArray2Formatted($this->_formatHolder, $this->resultRaw);
    }

    public function checkDomainBunch($domain, $tlds)
    {
        if (!$this->init_socket())
        {
            throw new APIException('oSRS Error - Unable to establish socket: (' . $this->_socketErrorNum . ') ' . $this->_socketErrorMsg);
        }

        if (preg_match("/(^.+)\.(.+)\.(.+)/", $domain, $matches) > 0)
        {
            $domain = $matches[1];
        }
        elseif (preg_match("/(^.+)\.(.+)/", $domain, $matches) > 0)
        {
            $domain = $matches[1];
        }

        $resultArray = [];
        foreach ($tlds as $tld)
        {

            $callCheck = 'check_domain ' . $domain . $tld;

            $callLength = strlen($callCheck);
            fputs($this->_socket, $callCheck, $callLength);

            $result = fread($this->_socket, 1024);

            $checkRes = $this->parseResult($result);

            $loopAray           = [];
            $loopAray['domain'] = $domain;
            $loopAray['tld']    = $tld;
            $loopAray['result'] = $checkRes;

            array_push($resultArray, $loopAray);
        }

        $this->close_socket();

        return $resultArray;
    }

    /**
     * Get the domain from the dataObject.
     */
    public function getDomain()
    {
        return $this->dataObject->data->domain;
    }

    public function convertArray2Formatted($type = '', $data = '')
    {
        $resultString = '';
        if ($type == 'json')
        {
            $resultString = json_encode($data);
        }
        if ($type == 'yaml')
        {
            $resultString = Spyc::YAMLDump($data);
        }

        return $resultString;
    }

    public function setDataObject($format, $dataObject)
    {
        $this->dataObject = $dataObject;
        $this->dataFormat = $format;
    }

    /**
     * Does the dataObject have a domain set?
     *
     * @return bool
     */
    public function hasDomain()
    {
        return isset($this->dataObject->data->domain);
    }
}
