<?php

/**
 * @uri /inventory
 */
class Inventory extends CfProtectedResource
{
    /**
     * @api {post} inventory Reports
     *
     * @apiName Inventory
     * @apiGroup Inventory
     * @apiVersion 1.0.0
     * @apiHeader {String} Authorization User token. Exmp.: `Bearer f9c6000853a90e4043b745263786777e0ff0011e`
     * @apiHeader {String=application/json} Content-Type
     *
     * @apiParam {array} select  Fields for selecting Emp.: `["Host name", "OS type", "IPv4 addresses", "CFEngine version","Ports listening"]`
     * @apiParam {json} [filter] Filter data Emp.: `{":field_name" : {":operator" : ":field_value", ":operator" : ":field_value"}, ":field_name" : {":operator" : ":field_value"}`
     * @apiParam {json} sort Field name for sorting with "-" for DESC order. Emp: `{"sort" : "-Host name"}`
     * @apiParam {integer} [start] Number of results to skip for the processed query. Optional parameter.
     * @apiParam {integer} [limit] Limit the number of results in the query. Default value is 1000, max value is 10000.
     * @apiParam {array} [hostContextInclude]   Includes value for filtering.
     * @apiParam {array} [hostContextExclude]   Excludes value for filtering.
     *
     * @apiParam (Filter parameters) {string} [field_name]    Name of field for filtering
     * @apiParam (Filter parameters) {string=lt,gt,eq,neq,lteq,gteq,l,nl,il,nil} [operator]    Operator for filtering.
     * @apiParam (Filter parameters) {string} [field_value]    Value of field for filtering.
     *
     * @apiSuccessExample Success-Response:
     * HTTP/1.1 200 OK
     *{
     *  "data": [
     *    {
     *      "header": [
     *        {
     *          "columnName": "hostkey",
     *          "columnType": "STRING"
     *        },
     *        {
     *          "columnName": "values",
     *          "columnType": "STRING"
     *        }
     *      ],
     *      "queryTimeMs": 293,
     *      "rowCount": 1,
     *      "rows": [
     *        [
     *          "SHA=0713d888be810b110bf710b569b0a3594dcf586a0418db4b677ea17ccbe1488c",
     *          "{\"default.sys.interfaces\" : \" {\"enp0s3\",\"enp0s8\"}\", \"default.sys.fqhost\" : \"localhost\", \"default.sys.hardware_addresses\" : \"   {\"08:00:27:b0:12:47\",\"08:00:27:c5:9a:83\"}\", \"default.sys.cpus\" : \"2\", \"default.sys.class\" : \"linux\", \"default.sys.release\" : \"4.8.0-36-generic\", \"default.sys.key_digest\" : \"SHA=0713d888be810b110bf710b569b0a3594dcf586a0418db4b677ea17ccbe1488c\", \"default.sys.cf_version\" : \"3.11.0a.5c98a70\", \"default.sys.arch\" : \"x86_64\", \"default.cfe_autorun_inventory_ipv4_addresses.ipv4[192.168.56.103]\" : \"192.168.56.103\", \"default.cfe_autorun_inventory_ipv4_addresses.ipv4[10.0.2.15]\" : \"10.0.2.15\", \"default.cfe_autorun_inventory_cpuinfo.cpu_model\" : \"Intel(R) Core(TM) i3-4160 CPU @ 3.60GHz\", \"default.cfe_autorun_inventory_dmidecode.dmi[bios-version]\" : \"VirtualBox\", \"default.cfe_autorun_inventory_dmidecode.dmi[system-manufacturer]\" : \"innotek GmbH\", \"default.cfe_autorun_inventory_dmidecode.dmi[system-serial-number]\" : \"0\", \"default.cfe_autorun_inventory_dmidecode.dmi[system-product-name]\" : \"VirtualBox\", \"default.cfe_autorun_inventory_dmidecode.dmi[bios-vendor]\" : \"innotek GmbH\", \"default.inventory_os.description\" : \"Ubuntu 16.04\", \"default.cfe_autorun_inventory_dmidecode.dmi[system-version]\" : \"1.2\", \"default.cfe_autorun_inventory_proc_cpuinfo.cpuinfo_physical_socket_inventory\" : \"1\", \"default.cfe_autorun_inventory_cpuinfo.cpuinfo_physical_cores\" : \"2\", \"default.cfe_autorun_inventory_memory.total\" : \"6393.29\", \"default.sys.uptime\" : \"4057\", \"default.cfe_autorun_inventory_listening_ports.ports\" : \" {\"22\",\"53\",\"80\",\"443\",\"5308\",\"5432\"}\", \"default.cfe_autorun_inventory_disk.free\" : \"84.00\", \"policy_server\" : \"policy_server\"}"
     *        ]
     *      ]
     *    }
     *  ],
     *  "meta": {
     *    "count": 1,
     *    "page": 1,
     *    "timestamp": 1495020761,
     *    "total": 1
     *  }
     *}
     * @apiErrorExample {string} Wrong operator:
     *     HTTP/1.1 500 Internal Server Error
     *       Wrong abbreviation of operator
     *
     * @rbacName Get inventory report
     * @rbacGroup Inventory API
     * @rbacAlias inventory.post
     * @rbacAllowedByDefault
     */
    public function post($request)
    {
        $inputData = Utils::getValidJsonData($request->data);

        $response = new Response($request);
        $response->code = Response::OK;
        $inventoryLib = new InventoryLib(new VariablesDictionaryModel());

        if (isset($inputData->group) && !empty($inputData->group)) {
            // set filter data from the group when it was set
            $inventoryLib->setFilterFromGroup($inputData, $this->username);
        }

        $where = $inventoryLib->applyFilter($inputData);
        $sort = $inventoryLib->applySorting($inputData);
        $select = $inventoryLib->applySelect($inputData);


        $data['query'] = 'SELECT ' . $select . ' FROM ' . INVENTORY_VIEW_NAME . ' ' . $where . $sort;
        $data['limit'] = isset($inputData->limit) ? $inventoryLib->getLimit($inputData->limit) : 0;
        ;
        $data['skip'] = $inputData->start ?? 0;
        $data['sortDescending'] = false;
        $data['sortColumn'] = "";

        $showSQL = isset($inputData->showSQL) && $inputData->showSQL === true;
        $response = new Response($request);

        if (!is_int($data['skip'])) {
            throw new InvalidArgumentException("'skip' field must be an integer");
        }

        if (!is_int($data['limit'])) {
            throw new InvalidArgumentException("'limit' field must be an integer");
        }

        if (isset($data['hostContextInclude']) && !is_array($data['hostContextInclude'])) {
            throw new InvalidArgumentException("'hostContextInclude' field must be an array");
        } else {
            $data['hostContextInclude'] = [];
        }

        if (isset($data['hostContextExclude']) && !is_array($data['hostContextExclude'])) {
            throw new InvalidArgumentException("'hostContextExclude' field must be an array");
        } else {
            $data['hostContextExclude'] = [];
        }

        $response->body = $inventoryLib->changeResponse(
            cfapi_query_post(
                $this->username,
                $data['query'],
                $data['sortColumn'] ?? '',
                $data['sortDescending'] ?? false,
                $data['skip'] ?? -1,
                $data['limit'] ?? -1,
                $data['hostContextInclude'] ?? [],
                $data['hostContextExclude'] ?? []
            ),
            $showSQL
        );
        return $response;
    }
}
