<?php

namespace MGModule\DNSManager2\mgLibs\custom\dns\submodules\AWSRoute53;
use MGModule\DNSManager2\mgLibs\custom\dns\record\RRSet;
use MGModule\DNSManager2\mgLibs\custom\dns\submodules\AWSRoute53 as awsRoute53;

class AWSRoute53API
{
    private $requestHandler;

    public function __construct(awsRoute53\AWSRoute53RequestInterface $requestHandler)
    {
        $this->requestHandler = $requestHandler;
    }

    public function createZone($name, $delegationSetId = false)
    {
        $body = $this->getCreateBody($name, $delegationSetId);

        return $this->requestHandler->makeRequest('/2013-04-01/hostedzone', 'POST', __FUNCTION__, $body);
    }

    public function listZones()
    {
        return $this->requestHandler->makeRequest('/2013-04-01/hostedzone', 'GET', __FUNCTION__);
    }

    public function testConnection()
    {
        return $this->requestHandler->makeRequest('/2013-04-01/hostedzone?maxitems=10', 'GET', __FUNCTION__);
    }

    public function listZonesByName($name)
    {
        return $this->requestHandler->makeRequest('/2013-04-01/hostedzonesbyname?dnsname='.$name, 'GET', __FUNCTION__);
    }

    public function deleteHostedZone($id)
    {
        return $this->requestHandler->makeRequest('/2013-04-01'.$id, 'DELETE', __FUNCTION__);
    }

    public function getHostedZoneById($id)
    {
        return $this->requestHandler->makeRequest('/2013-04-01'.$id, 'GET', __FUNCTION__);
    }

    public function listRecords($zoneId)
    {
        return $this->requestHandler->makeRequest("/2013-04-01".$zoneId."/rrset", 'GET', __FUNCTION__);
    }

    public function updateRecord($zoneId, $record, $aliasType = false)
    {
        $cleanZoneId = $this->cleanZoneId($zoneId);
        $body = $this->getRecordBody($cleanZoneId, $record, 'UPSERT', $aliasType);

        return $this->requestHandler->makeRequest("/2013-04-01".$zoneId."/rrset/", 'POST', __FUNCTION__, $body);
    }

    public function updateRRSet( RRSet $RRSet, $zoneId ,$aliasType = false)
    {
        $cleanZoneId = $this->cleanZoneId($zoneId);
        $body = $this->getRecordBody($cleanZoneId, AWSRoute53ResponseParseHelper::createUnifiedRecordFromRRSet($RRSet), 'UPSERT',$aliasType);
        return $this->requestHandler->makeRequest("/2013-04-01".$zoneId."/rrset/", 'POST', __FUNCTION__, $body);
    }

    public function removeRRSet( RRSet $RRSet, $zoneId ,$aliasType = false)
    {
        $cleanZoneId = $this->cleanZoneId($zoneId);
        $body = $this->getRecordBody($cleanZoneId, AWSRoute53ResponseParseHelper::createUnifiedRecordFromRRSet($RRSet), 'DELETE',$aliasType);
        return $this->requestHandler->makeRequest("/2013-04-01".$zoneId."/rrset/", 'POST', __FUNCTION__, $body);
    }

    public function deleteRecord($zoneId, $record, $aliasType = false)
    {
        $cleanZoneId = $this->cleanZoneId($zoneId);
        $body = $this->getRecordBody($cleanZoneId, $record, 'DELETE', $aliasType);

        return $this->requestHandler->makeRequest("/2013-04-01".$zoneId."/rrset/", 'POST', __FUNCTION__, $body);
    }

    public function createRecord($zoneId, $record, $aliasType = false)
    {
        $cleanZoneId = $this->cleanZoneId($zoneId);
        $body = $this->getRecordBody($cleanZoneId, $record, 'UPSERT', $aliasType);
        return $this->requestHandler->makeRequest("/2013-04-01".$zoneId."/rrset/", 'POST', __FUNCTION__, $body);
    }

    private function getCreateBody($name, $delegationSetId = false)
    {
        $params = array(
            'callerReference' => $this->getCallerReference(),
            'zoneName' => $name,
            'delegationSetId' => $delegationSetId
        );

        $templateName = ($delegationSetId && $delegationSetId !== '')
            ? awsRoute53\AWSRoute53XmlRequestHelper::ZONE_REQUEST_DELEGATION_SET
            : awsRoute53\AWSRoute53XmlRequestHelper::ZONE_REQUEST;

        $body = awsRoute53\AWSRoute53XmlRequestHelper::prepareResponseBody($templateName, $params);

        return $body;
    }

    private function getRecordBody($zoneId, $record, $action, $aliasType = false)
    {
        $recordType = $aliasType ? $aliasType : $record->type;

        $finalRecord        = '';

        foreach( explode(PHP_EOL, $record->rdata->toString()) as $recordNS )
        {
            $finalRecord .= $this->getNsResourceBody(str_replace("\t",'',$recordNS));
        }

        $params = array(
            'action' => $action,
            'recordName' => $record->name,
            'recordTtl' => $record->ttl,
            'recordType' => $recordType,
            'targetName' => $record->rdata->target,
            'hostedZoneId' => $zoneId,
            'recordValue' =>str_replace("\t", ' ',  $record->rdata->toString()),
            'nsResourceRecords' => $finalRecord
        );

        switch($recordType)
        {
            case 'A':
                $template = awsRoute53\AWSRoute53XmlRequestHelper::RECORD_NS_REQUEST;
                break;
            case 'AAAA':
                $template = awsRoute53\AWSRoute53XmlRequestHelper::RECORD_NS_REQUEST;
                break;
            case 'NS':
            case 'TXT':
                $template = awsRoute53\AWSRoute53XmlRequestHelper::RECORD_NS_REQUEST;
                break;
            case 'MX':
                $template = awsRoute53\AWSRoute53XmlRequestHelper::RECORD_NS_REQUEST;
                break;
            default:
                $template = awsRoute53\AWSRoute53XmlRequestHelper::RECORD_REQUEST;
                break;
        }

        $template = $aliasType ? awsRoute53\AWSRoute53XmlRequestHelper::RECORD_ALIAS_REQUEST : $template;

        $body = awsRoute53\AWSRoute53XmlRequestHelper::prepareResponseBody($template, $params);

        return $body;
    }

    public function getCallerReference()
    {
        return time();
    }

    public function cleanZoneId($zoneId)
    {
        if(strpos($zoneId, "/hostedzone/") || strpos($zoneId, "/hostedzone/") === 0)
        {
            return str_replace("/hostedzone/", "", $zoneId);
        }

        if(strpos($zoneId, "hostedzone/") || strpos($zoneId, "hostedzone/") === 0)
        {
            return str_replace("hostedzone/", "", $zoneId);
        }

        return $zoneId;
    }

    public function getNsResourceBody($rData)
    {
        $hosts = explode(PHP_EOL, $rData);
        $rBody = '';
        foreach($hosts as $host)
        {
            $rBody .= awsRoute53\AWSRoute53XmlRequestHelper::prepareResponseBody(awsRoute53\AWSRoute53XmlRequestHelper::RECORD_NS_HOST,
                array('hostName' => $host));
        }

        return $rBody;
    }
}
