<?php

namespace PriaxSync\Managers;

use PriaxSync\Entity\Host as Entity;
use PriaxSync\Entity\HostExtInfo as ExtInfo;
use PriaxSync\Logger;

/**
 * Class Host
 */
final class Host
{
    const RETRY = 10;

    /**
     * @var \ConfigManager
     */
    private $manager;

    /**
     * @var Logger
     */
    private $logger;

    /**
     * Constructor
     *
     * @param Logger $logger
     * @param \ConfigManager $manager
     */
    public function __construct(Logger $logger, \ConfigManager $manager = null)
    {
        $this->logger = $logger;
        $this->manager = $manager ?: new \ConfigManager;
    }

    public function save(array $info)
    {
        $info['use_template_id'] = $this->manager->getTemplateIdByName($info['template_name']);
        if (!isset($info['host_name']) || empty($info['host_name'])) {
            $ic_info = '';
            foreach ($info as $key => $value) {
                if (empty($ic_info)) {
                    $ic_info = $key." => ".$value;
                }
                else {
                    $ic_info .= " / ".$key." => ".$value;
                }
            }
            $this->logger->error('IC: Missing host_name property from IC '.$ic_info);
            return false;
        }
        $host = new Entity($info);
        $hostExtInfo = new ExtInfo($info);

        return $this->hasCreated($host)
            ? $this->modify($host, $hostExtInfo)
            : $this->add($host, $hostExtInfo);
    }

    protected function modify(Entity $host, ExtInfo $hostExtInfo)
    {
        if ($this->manager->modifyHostConfig($host->toArray(), $hostExtInfo->toArray())) {
            return $host->host_id;
        }
        $this->logger->debug('Could not MODIFY IC - array '. var_export($host->toArray(), true));
        $this->logger->debug('Could not MODIFY IC - object '. var_export($host->toArray(), true));
    }

    protected function add(Entity $host, ExtInfo $hostExtInfo)
    {
        $count = 1;
        do {
            $id = $this->manager->addHost($host->toArray(), $hostExtInfo->toArray());
            $count++;
        } while ($id <= 0 && $count < self::RETRY);

        if ($id <= 0) {
            $this->logger->debug('Could not ADD IC - array '. var_export($host->toArray(), true));
            $this->logger->debug('Could not ADD IC - object '. var_export($host, true));
        }

        return $id;
    }

    protected function modifyHostName(Entity $host, $count)
    {
        $tmp = clone $host;
        if ($count > 1) {
            $tmp->host_name = str_replace('(', ":{$count}(", $host->host_name);
            //$this->logger->debug(sprintf('Modifying host name from %s to %s', $host->host_name, $tmp->host_name));
        }

        return $tmp;
    }

    protected function hasCreated(Entity $host)
    {
        $host = $this->manager->getOneHostBy(
            'host_id = ?',
            array($host->host_id),
            array('host_id')
        );

        return ($host['host_id'] > 0);
    }

    public function delete(array $info)
    {
        //$this->logger->info(sprintf('Deleting host %s cmdb_id [%d]', $info['host_name'], $info['cmdb_id']));
        return $this->manager->deleteHostBy('cmdb_id = ?', array($info['cmdb_id']));
    }

    public function deleteByCmdbId($id)
    {
        //$this->logger->info(sprintf('Deleting host cmdb_id [%d]', $id));
        return $this->manager->deleteHostBy('cmdb_id = ?', array($id), true); // true to remove CMDB children
    }

    public function deleteAllNotIn(array $activedIDs)
    {
        //$this->logger->info("Deleting All Inactive Host");
        $where = sprintf('cmdb_id not in (%s)', implode(', ', $activedIDs));
        return $this->manager->deleteHostBy($where);
    }

    public function addParent($childId, $parentId)
    {
        //$this->logger->info(sprintf('Linking child [%d] to parent [%d]', $childId, $parentId));
        return $this->manager->add_parent($childId, $parentId);
    }

    public function addRelationships(array $relationships)
    {
        foreach ($relationships as $relationship) {
            $this->addParent($relationship->sonOpmonId, $relationship->parentOpmonId);
        }

        return true;
    }

    public function getLogger()
    {
        return $this->logger;
    }

    public function getConfigManager()
    {
        return $this->manager;
    }
}
