<?php

namespace MGModule\DNSManager2\mgLibs\custom\helpers;
use MGModule\DNSManager2 as main;
use MGModule\DNSManager2\mgLibs\custom\dns as dns;
use MGModule\DNSManager2\mgLibs\custom\helpers\ZoneLogger\Manager as ZoneLoggerManager;


/**
 * Upadting zone record sets
 *
 * @author 
 */
class ZoneUpdateHelper
{
    private $zone;
    private $backup;
    private $module;
    
    private $backupRecords = array();

    /**
     * @var ZoneLoggerManager
     */
    private $zoneLoggerManager;
    
    public function __construct($sourceZone, $backup, ZoneLoggerManager $zoneLoggerManager)
    {
        $this->zone = $sourceZone;
        $this->backup = $backup;
        $this->module = $this->zone->getModule();
        $this->bulidBackupRecords();
        $this->zoneLoggerManager = $zoneLoggerManager;
    }
    
    public function update()
    {
        $currentRecords = $this->module->getRecords();
        $tmpBackupRecords = $this->backupRecords;

        $curCname = false;
        $soaLine = '';
        $soaSerial = '';
        foreach($currentRecords as $rKey => $cRecord)
        {
            foreach($tmpBackupRecords as $brKey => $bRecord)
            {
                if($cRecord === null || $bRecord === null)
                {
                    continue;
                }
                
                if($cRecord->type === 'SOA')
                {
                    $curCname = true;
                    $soaLine = $cRecord->line;
                    $soaSerial = $cRecord->$soaSerial->serial;
                }
                
                if($this->compareRecords($cRecord, $bRecord) === true)
                {
                    unset($currentRecords[$rKey]);
                    unset($cRecord);
                    unset($tmpBackupRecords[$brKey]); unset($bRecord);
                }
            }
        }
        $errorMessage = '';
        foreach($tmpBackupRecords as $bdRecord)
        {
            try {
                if($bdRecord->type === 'SOA' && $curCname)
                {
                    $bdRecord->line = $soaLine;
                    $bdRecord->rdata->serial = $soaSerial;
                    $this->module->editRecord($bdRecord);
                    continue;
                }
                $this->module->addRecord($bdRecord);
                $this->zoneLoggerManager->logAddRecordToZone($this->zone, $bdRecord, 'Export: ');
            } catch (\Exception $e) {
                $errorMessage .= "<b>Record: " . $bdRecord->name . " - " . $bdRecord->type . " - " . $bdRecord->rdata->toString() . ": </b>" . $e->getMessage() . "\n";
            }
        }

        if($errorMessage)
            throw new \Exception($errorMessage);

        foreach($currentRecords as $cdRecord)
        {
            $cRecords = $this->module->getRecords();
            foreach($cRecords as $cValue)
            {
                if($cValue->type === 'SOA' && $curCname)
                {
                    continue;
                }
                if($this->compareRecords($cdRecord, $cValue))
                {
                    $this->module->deleteRecord($cValue);
                    $this->zoneLoggerManager->logRemoveRecordFromZone($this->zone, $cValue, 'Export: ');
                }                
            }
        }        
    }
    
    protected function bulidBackupRecords()
    {
        $recordList = array();
        $backupRecords = $this->backup->zoneRecords;
        foreach($backupRecords as $bRecord)
        {
            $recordList[] = $this->buildRecordFromStd($bRecord);      
        }
        
        $this->backupRecords = $recordList;
    }
    
    protected function buildRecordFromStd($stdOb)
    {
        $record = new main\mgLibs\custom\dns\record\Record();
        $record->name = $stdOb->name;
        $record->type = $stdOb->type;
        $record->ttl  = $stdOb->ttl;
        $record->createRDATAObject();
        $record->rdata->setDataFromArray($this->buildRdataFromStd($stdOb->type, $stdOb->rdata));

        return $record;        
    }
    
    protected function buildRdataFromStd($rType, $stdRdataOb)
    {
        $rDataValues = array();
        $className = "\\MGModule\\DNSManager2\\mgLibs\\custom\\dns\\record\\type\\".$rType;
        if(class_exists($className))
        {
            $rec = new $className;
            $obVars = get_object_vars($rec);
            foreach($obVars as $key => $var)
            {
                $rDataValues[$key] = $stdRdataOb->$key;
            }
        }
        
        return $rDataValues;
    }
    
    protected function compareRecords(dns\record\Record $rec1, dns\record\Record $rec2)
    {
        if($rec1->name === $rec2->name && (int)$rec1->ttl === (int)$rec2->ttl && $rec1->type === $rec2->type
            && $rec1->rdata->toString() === $rec2->rdata->toString())
        {
            return true;
        }
        
        return false;
    }
    
}
