<?php

/**
 * @uri /query/async/:token 2
 */
class QueryAsyncId extends CfProtectedResource
{
    /**
     * @param $request
     * @param $token
     *
     * @rbacName Get async query status
     * @rbacGroup Query API
     * @rbacAlias queryAsyncId.get
     * @rbacAllowedByDefault
     *
     * @return Response
     */
    public function get($request, string $token)
    {
        $user = $this->username;

        $response = new Response($request);

        $static_files_uri = Utils::baseUri() . '/tmp/';

        $payload = cfapi_query_async_get($user, $token, $static_files_uri);
        if ($payload) {
            $response->code = Response::OK;
            $response->body = $payload;
        } else {
            $response->code = Response::NOTFOUND;
        }

        return $response;
    }

    /**
     * @param $request
     * @param $token
     *
     * @rbacName Abort async query
     * @rbacGroup Query API
     * @rbacAlias queryAsyncId.delete
     * @rbacAllowedByDefault
     *
     * @return Response
     */
    public function delete($request, string $token)
    {
        $user = $this->username;

        $response = new Response($request);

        if (cfapi_query_async_delete($user, $token)) {
            $response->code = Response::NOCONTENT;
        } else {
            $response->code = Response::INTERNALSERVERERROR;
        }

        return $response;
    }
}



/**
 * @uri /query/async 1
 */
class QueryAsync extends CfProtectedResource
{
    /**
     * @param $request
     *
     * @rbacName Create async query
     * @rbacGroup Query API
     * @rbacAlias queryAsync.post
     * @rbacAllowedByDefault
     *
     * @return Response
     * @throws ResponseException
     */
    public function post($request)
    {
        $username = $this->username;
        $response = new Response($request);

        $data = Utils::getValidJsonData($request->data);

        if (!$data->query || !is_string($data->query)) {
            $response->code = Response::BADREQUEST;
            $response->body = "'query' field is required";
            return $response;
        }

        /*
         * Supported formats:
         *  - CSV      (default)
        */
        if (!$data->outputType) {
            $data->outputType = 'csv';
        } elseif ($data->outputType != 'csv') {
            $response->code = Response::BADREQUEST;
            $response->body = "Unknown 'outputType'. Supported types: 'csv' . Leave empty for default(csv)";
            return $response;
        }

        if ($data->hostContextInclude) {
            if (!is_array($data->hostContextInclude)) {
                $response->code = Response::BADREQUEST;
                $response->body = "'hostContextInclude' field must be an array";
                return $response;
            }
        } else {
            $data->hostContextInclude = array();
        }

        if ($data->hostContextExclude) {
            if (!is_array($data->hostContextExclude)) {
                $response = new Response($request);
                $response->code = Response::BADREQUEST;
                $response->body = "'hostContextExclude' field must be an array";
                return $response;
            }
        } else {
            $data->hostContextExclude = array();
        }

        $response = new Response($request);
        $response->body = cfapi_query_async_post(
            $username,
            $data->query,
            $data->outputType,
            $data->hostContextInclude,
            $data->hostContextExclude
        );
        $response->code = Response::OK;

        return $response;
    }
}

/**
 * @uri /query 0
 */
class Query extends CfProtectedResource
{
    /**
     * @param $request
     *
     * @rbacName Run query
     * @rbacGroup Query API
     * @rbacAlias query.post
     * @rbacAllowedByDefault
     *
     * @return Response
     * @throws ResponseException
     */
    public function post($request)
    {
        $username = $this->username;

        $data = Utils::getValidJsonData($request->data);

        if (!isset($data->query)) {
            $response = new Response($request);
            $response->code = Response::BADREQUEST;
            $response->body = "'query' field is required";
            return $response;
        }

        if (!isset($data->sortDescending)) {
            $data->sortDescending = false;
        }

        if (!isset($data->sortColumn)) {
            $data->sortColumn = "";
        }

        if (isset($data->skip)) {
            if (gettype($data->skip) !== "integer") {
                $response = new Response($request);
                $response->code = Response::BADREQUEST;
                $response->body = "'skip' field must be an integer";
                return $response;
            }
        } else {
            $data->skip = -1;
        }

        if (isset($data->limit)) {
            if (gettype($data->limit) !== "integer") {
                $response = new Response($request);
                $response->code = Response::BADREQUEST;
                $response->body = "'limit' field must be an integer";
                return $response;
            }
        } else {
            $data->limit = -1;
        }

        if (isset($data->hostContextInclude)) {
            if (!is_array($data->hostContextInclude)) {
                $response = new Response($request);
                $response->code = Response::BADREQUEST;
                $response->body = "'hostContextInclude' field must be an array";
                return $response;
            }
        } else {
            $data->hostContextInclude = array();
        }

        if (isset($data->hostContextExclude)) {
            if (!is_array($data->hostContextExclude)) {
                $response = new Response($request);
                $response->code = Response::BADREQUEST;
                $response->body = "'hostContextExclude' field must be an array";
                return $response;
            }
        } else {
            $data->hostContextExclude = array();
        }

        $response = new Response($request);
        $response->body = cfapi_query_post(
            $username,
            $data->query,
            $data->sortColumn,
            $data->sortDescending,
            $data->skip,
            $data->limit,
            $data->hostContextInclude,
            $data->hostContextExclude
        );
        $response->code = Response::OK;

        return $response;
    }
}

/**
 * @uri /inventory-filtered-query 0
 */
class QueryWithInventoryFilter extends Query
{
    public function post($request)
    {
        $data = Utils::getValidJsonData($request->data);
        $inventoryLib = new InventoryLib(new VariablesDictionaryModel());
        if ($data->filter) {
            $inventoryLib->extendSQLWithInventoryCTE($data);
        }

        $request->data = json_encode($data);

        return parent::post($request);
    }
}
