<?php

namespace idoit\Module\JDisc\Graphql\Mutation\Discovery;

use GraphQL\Mutation;
use GraphQL\Query;
use GraphQL\RawObject;
use GraphQL\Results;
use idoit\Module\JDisc\Graphql\AbstractGraphql;
use idoit\Module\JDisc\Graphql\ParameterBagInterface;
use idoit\Module\JDisc\Graphql\ResponseInterface;
use idoit\Module\JDisc\Graphql\Schema\Model\DiscoveryProtocolEnum;
use idoit\Module\JDisc\Graphql\Schema\Model\DiscoveryProtocolStatusEnumEnum;
use idoit\Module\JDisc\Graphql\Type\AbstractType;
use idoit\Module\JDisc\Graphql\Type\StringType;

class DiscoverDevice extends AbstractGraphql implements ParameterBagInterface, ResponseInterface
{
    private StringType $ipOrHostname;

    private StringType $id;

    /**
     * @param StringType $ipOrHostname
     */
    public function setIpOrHostname(StringType $ipOrHostname): void
    {
        $this->ipOrHostname = $ipOrHostname;
    }

    /**
     * @param StringType $id
     */
    public function setID(StringType $id): void
    {
        $this->id = $id;
    }

    /**
     * @return array
     */
    public static function getSuccessFlags()
    {
        return [
            DiscoveryProtocolStatusEnumEnum::Success,
            DiscoveryProtocolStatusEnumEnum::ItemAlreadyInQueue,
        ];
    }

    /**
     * @return StringType[]
     */
    public function getParameters(): array
    {
        if (isset($this->ipOrHostname)) {
            return [
                $this->ipOrHostname
            ];
        }

        return [];
    }

    /**
     * @return string[]
     */
    public function getSelections(): array
    {
        return [
            'status'
        ];
    }

    /**
     * @return Query
     */
    public function getQuery(): Query
    {
        $query = (new Mutation('discovery'))
            ->setVariables($this->buildVariables())
            ->setSelectionSet(
                [
                    (new Query('trigger'))
                        ->setSelectionSet(
                            [
                                isset($this->ipOrHostname)
                                ? (new Query('triggerDeviceScan'))
                                    ->setArguments($this->buildArguments())
                                    ->setSelectionSet($this->getSelections())
                                : (new Query('triggerExistingDeviceScan'))
                                    ->setArguments([
                                        'lookupDeviceFirst' => false,
                                        'deviceReference'   => new RawObject('{id: ' . $this->id->getFormattedValue() . '}'),
                                    ])
                                    ->setSelectionSet($this->getSelections())
                            ]
                        )

                ]
            );

        return $query;
    }

    /**
     * @param Results $results
     *
     * @return array
     */
    public static function getDataFromResults(Results $results): array
    {
        $data = $results->getData();

        if (isset($data['discovery']['trigger']['triggerExistingDeviceScan'])) {
            return $data['discovery']['trigger']['triggerExistingDeviceScan'];
        }

        return isset($data['discovery']['trigger']['triggerDeviceScan']) ?
            $data['discovery']['trigger']['triggerDeviceScan'] : [];
    }
}
