<?php

require_once APPPATH . 'libraries/Cf_REST_Controller.php';

class Astrolabe extends Cf_REST_Controller
{

    function __construct()
    {
        parent::__construct();
        $this->load->model('astrolabe_model');
        $this->load->model('host_model');
        $this->username = $this->session->userdata('username');
        $this->load->driver('cache', array('adapter' => 'file'));
    }

    function host_post()
    {
        $page = isset($_REQUEST['page']) ? $_REQUEST['page'] : 1;
        //If the count doesn't set, set it to 999999 (as no limit)
        $count = isset($_REQUEST['count']) ? $_REQUEST['count'] : UNLIMITED_COUNT;
        $hosts = $this->host_model->getHostListByContext($this->param_includes(), $this->param_excludes(), false, $page, $count);
        $this->respond(200, json_encode($hosts));
    }

    function profile_get($id = NULL, $shared = NULL, $sharedFrom = NULl)
    {

        if (is_null($id))
        {
            $roles = $this->session->userdata('roles') ? $this->session->userdata('roles') : array();
            $profileList = $this->astrolabe_model->profile_list($this->username, $roles);
            $this->respond(200, json_encode($profileList));
        }
        else
        {
            $roles = $this->session->userdata('roles') ? $this->session->userdata('roles') : array();
            $profile = $this->astrolabe_model->profile_get($this->username, $id, $shared, $sharedFrom, '{'. implode(',',$roles) .'}');
            if ($profile !== null)
            {
                $this->respond(200, json_encode($profile->data));
            }
            else
            {
                $this->respond(404);
            }
        }
    }

    function profile_put($profileName)
    {
        $profileName = urldecode($profileName);

        if (!$this->isValidName($profileName))
        {
            $this->respond_not_acceptable();
            return;
        }

        $data = json_decode($this->_put_args, true);
        $node_description_list = $data['nodeDescription'];
        if ($this->__is_valid_node_description_list($node_description_list))
        {
            $sharedPermission = !empty($data['sharedPermission']) ? $data['sharedPermission'] : array();
            $global = !empty($data['global']) ? $data['global'] : false;
            $meta = array('sharedPermission' => $sharedPermission, 'globaltree' => $global);
            $id = $this->astrolabe_model->profile_insert($this->username, $profileName, $node_description_list, $meta);
            $responseData = array('id' => $id);
            $this->respond_ok(json_encode($responseData));
        }
        else
        {
            $this->respond_not_acceptable();
        }
    }

    function profile_post($id)
    {
        $newName = $this->param('newname', true);
        $nodeData = $this->param('nodeData', true);
        $global = $this->param('globalTree', true);
        $sharedPermission = $this->param('sharedPermission', true);

        $updateData = array();
        if (!empty($newName))
        {

            if (!$this->isValidName($newName))
            {
                $this->respond_not_acceptable();
                return;
            }
            $updateData['profileId'] = $newName;
        }
        if (!empty($nodeData))
        {
            $updateData['data'] = json_decode($nodeData, true);
        }
        if ($global !== FALSE)
        {
            $updateData['globaltree'] = (bool) $global;
        }
        if ($sharedPermission)
        {
            $updateData['sharedPermission'] = $sharedPermission;
        }

        $result = $this->astrolabe_model->profile_update($this->username, $id, $updateData);

        if (is_array($result) && !empty($result['err']))
        {
            $this->respond(500, "Error updating tree name");
        }

        $this->respond_ok();
    }

    function profile_delete($id)
    {
        if ($this->astrolabe_model->profile_delete($this->username, $id) == true)
        {
            $this->respond(204);
        }
        else
        {
            $this->respond(500, "Error deleting profile");
        }
    }

    function subscribe_put($id)
    {
        $roles = $this->session->userdata('roles') ? $this->session->userdata('roles') : array();
        if ($this->astrolabe_model->subscription_put($this->username, $roles, $id))
        {
            $this->respond(200);
        }
        else
        {
            $this->respond(500, "Error subscribing.");
        }
    }

    function subscribe_delete($id)
    {
        if ($this->astrolabe_model->subscription_delete($this->username, $id))
        {
            $this->respond(200);
        }
        else
        {
            $this->respond(500, "Error subscribing.");
        }
    }

    function copy_put($id, $from)
    {
        $result = $this->astrolabe_model->copy_tree($this->username, $from, $id);
        if ($result)
        {
            $this->respond(200, json_encode($result));
        }
        else
        {
            $this->respond(500, "Error copying tree.");
        }
    }

    private function isValidName($name)
    {
        $pattern = "/^[a-zA-Z0-9 _-]{1,100}$/";
        return preg_match($pattern, $name) === 1;
    }

    function __is_valid_node_description_list($node_description_list)
    {
        if (!is_array($node_description_list))
        {
            return false;
        }

        foreach ($node_description_list as $child)
        {
            if (!$this->__is_valid_node_description($child))
            {
                return false;
            }
        }

        return true;
    }

    function __is_valid_node_description($node_description)
    {
        if (!array_key_exists('label', $node_description) ||
                !$node_description['label'])
        {
            return false;
        }

        $label = $node_description['label'];
        if (!$this->isValidName($label))
        {
            return false;
        }

        if (!array_key_exists('classRegex', $node_description) ||
                !$node_description['classRegex'])
        {
            return false;
        }

        if (array_key_exists('children', $node_description))
        {
            if (!$this->__is_valid_node_description_list($node_description['children']))
            {
                return false;
            }
        }

        return true;
    }

}
