<?php

use idoit\Module\SyneticsJdisc\Graphql\Connector;
use idoit\Module\SyneticsJdisc\Graphql\Mutation\Discovery\DiscoverDevice;
use idoit\Module\SyneticsJdisc\Graphql\Mutation\Discovery\StartJob;
use idoit\Module\SyneticsJdisc\Graphql\Query\GetDiscoveryLog;
use idoit\Module\SyneticsJdisc\Graphql\Query\IdentifyDevice;
use idoit\Module\SyneticsJdisc\Graphql\Query\Job\GetJobByName;
use idoit\Module\SyneticsJdisc\Graphql\Query\Job\GetJobs;
use idoit\Module\SyneticsJdisc\Graphql\Type\DeviceInputType;
use idoit\Module\SyneticsJdisc\Graphql\Type\DiscoveryJobReferenceType;
use idoit\Module\SyneticsJdisc\Graphql\Type\StringType;

class isys_jdisc_dao_discovery_graphql extends isys_jdisc_dao_discovery
{
    private int $serverId;

    /**
     * @param int $serverId
     *
     * @return $this
     */
    public function setServerId(int $serverId): isys_jdisc_dao_discovery_graphql
    {
        $this->serverId = $serverId;
        return $this;
    }

    /**
     * @param string $host unused
     * @param string $username unused
     * @param string $password unused
     * @param string $port unused
     * @param string $protocol unused
     *
     * @return $this|isys_jdisc_dao_discovery_graphql
     * @throws Exception
     */
    public function connect($host, $username, $password, $port = '', $protocol = 'http')
    {
        $connector = Connector::instance($this->serverId);
        $connector->connect();
        return $this;
    }

    /**
     * @return isys_jdisc_dao_discovery_graphql
     */
    public function disconnect()
    {
        $connector = Connector::instance($this->serverId);
        $connector->disconnect();
        return $this;
    }

    /**
     * @return array
     * @throws Exception
     */
    public function get_discovery_jobs()
    {
        $connector = Connector::instance($this->serverId);
        $connector->connect();

        $query = new GetJobs();
        return $connector->query($query);
    }

    /**
     * @return bool
     * @throws Exception
     */
    public function start_discovery_job()
    {
        try {
            $connector = Connector::instance($this->serverId);
            $connector->connect();

            $discoveryJob = $this->get_discovery_job();
            if (!is_array($discoveryJob) || !isset($discoveryJob['name'])) {
                return false;
            }

            if (!isset($discoveryJob['id'])) {
                $query = new GetJobByName();
                $query->setParameters([
                    new StringType('name', $discoveryJob['name'])
                ]);
                $data = $connector->query($query);
                $discoveryJob['id'] = $data[0]['id'];
            }

            $query = new StartJob();

            $startJobParameter = new DiscoveryJobReferenceType('discoveryJobReference', $discoveryJob['id']);
            $startJobParameter->setRequired(true);

            $query->setParameters([
                $startJobParameter,
            ]);
            $data = $connector->query($query);

            return in_array($data['startJob'], StartJob::getSuccessFlags());
        } catch (Exception $e) {

            return false;
        }
    }

    /**
     * @return bool
     */
    public function discover_device()
    {
        try {
            $connector = Connector::instance($this->serverId);
            $connector->connect();

            $query = new DiscoverDevice();

            $discoveryParameter = new StringType('ipOrHostname', $this->get_target());
            $discoveryParameter->setRequired(true);

            $query->setParameters([
                $discoveryParameter,
            ]);
            $data = $connector->query($query);
            return in_array($data[0]['status'], DiscoverDevice::getSuccessFlags());
        } catch (Exception $e) {
            return false;
        }
    }

    /**
     * @return bool
     */
    public function discover_device_by_serialnumber()
    {
        try {
            $connector = Connector::instance($this->serverId);
            $connector->connect();

            // identify device first
            $query = new IdentifyDevice();
            $query->setParameters([
                new DeviceInputType(
                    'device',
                    [
                        'serialNumber' => $this->get_target(),
                    ]
                ),
            ]);
            $data = $connector->query($query);
            if (empty($data['device']['id'])) {
                return false;
            }

            // then try to discover
            $query = new DiscoverDevice();
            $query->setParameters([
                new StringType('id', $data['device']['id']),
            ]);
            $data = $connector->query($query);

            return in_array($data[0]['status'], DiscoverDevice::getSuccessFlags());
        } catch (Exception $e) {
            return false;
        }
    }

    /**
     * @return array
     * @throws Exception
     */
    public function get_running_discover_status()
    {
        $connector = Connector::instance($this->serverId);
        $connector->connect();

        $query = new GetDiscoveryLog();
        return $connector->query($query);
    }
}
