<?php

defined('BASEPATH') OR exit('No direct script access allowed');

// This can be removed if you use __autoload() in config.php OR use Modular Extensions
/** @noinspection PhpIncludeInspection */
require __DIR__.'/REST_Controller.php';

/**
 * This is an example of a few basic user interaction methods you could use
 * all done with a hardcoded array
 *
 * @package         CodeIgniter
 * @subpackage      Rest Server
 * @category        Controller 
 */
class Projects extends REST_Controller {
    function __construct()
    {
        // Construct the parent class
        parent::__construct();
        $this->load->model('Api_model');
    }

    /**
     * @api {get} api/projects/:id Request project information
     * @apiName GetProject
     * @apiGroup Projects
     *
     * @apiHeader {String} authtoken Authentication token, generated from admin area
     *
     * @apiParam {Number} id project unique ID.
     *
     * @apiSuccess {Object} Project information.
     *
     * @apiSuccessExample Success-Response:
     *     HTTP/1.1 200 OK
     *     {
     *          "id": "28",
     *          "name": "Test1",
     *          "description": null,
     *          "status": "1",
     *          "clientid": "11",
     *          "billing_type": "3",
     *          "start_date": "2019-04-19",
     *          "deadline": "2019-08-30",
     *          "project_created": "2019-07-16",
     *          "date_finished": null,
     *          "progress": "0",
     *          "progress_from_tasks": "1",
     *          "project_cost": "0.00",
     *          "project_rate_per_hour": "0.00",
     *          "estimated_hours": "0.00",
     *          "addedfrom": "5",
     *          "rel_type": "lead",
     *          "potential_revenue": "0.00",
     *          "potential_margin": "0.00",
     *          "external": "E",
     *         ...
     *     }
     *
     * @apiError {Boolean} status Request status.
     * @apiError {String} message No data were found.
     *
     * @apiErrorExample Error-Response:
     *     HTTP/1.1 404 Not Found
     *     {
     *       "status": false,
     *       "message": "No data were found"
     *     }
     */
    public function data_get($id = '')
    {
        // If the id parameter doesn't exist return all the
        $data = $this->Api_model->get_table('projects', $id);

        // Check if the data store contains
        if ($data)
        {
            $data = $this->Api_model->get_api_custom_data($data, "projects", $id);

            // Set the response and exit
            $this->response($data, REST_Controller::HTTP_OK); // OK (200) being the HTTP response code
        }
        else
        {
            // Set the response and exit
            $this->response([
                'status' => FALSE,
                'message' => 'No data were found'
            ], REST_Controller::HTTP_NOT_FOUND); // NOT_FOUND (404) being the HTTP response code
        }
    }

    /**
     * @api {get} api/projects/search/:keysearch Search Project Information
     * @apiName GetProjectSearch
     * @apiGroup Projects
     *
     * @apiHeader {String} authtoken Authentication token, generated from admin area
     *
     * @apiParam {String} keysearch Search keywords.
     *
     * @apiSuccess {Object} Project information.
     *
     * @apiSuccessExample Success-Response:
     *     HTTP/1.1 200 OK
     *     {
     *          "id": "28",
     *          "name": "Test1",
     *          "description": null,
     *          "status": "1",
     *          "clientid": "11",
     *          "billing_type": "3",
     *          "start_date": "2019-04-19",
     *          "deadline": "2019-08-30",
     *          "project_created": "2019-07-16",
     *          "date_finished": null,
     *          "progress": "0",
     *          "progress_from_tasks": "1",
     *          "project_cost": "0.00",
     *          "project_rate_per_hour": "0.00",
     *          "estimated_hours": "0.00",
     *          "addedfrom": "5",
     *          "rel_type": "lead",
     *          "potential_revenue": "0.00",
     *          "potential_margin": "0.00",
     *          "external": "E",
     *         ...
     *     }
     *
     * @apiError {Boolean} status Request status.
     * @apiError {String} message No data were found.
     *
     * @apiErrorExample Error-Response:
     *     HTTP/1.1 404 Not Found
     *     {
     *       "status": false,
     *       "message": "No data were found"
     *     }
     */
    public function data_search_get($key = '')
    {
        $data = $this->Api_model->search('project', $key);

        // Check if the data store contains
        if ($data)
        {
            $data = $this->Api_model->get_api_custom_data($data,"projects");

            // Set the response and exit
            $this->response($data, REST_Controller::HTTP_OK); // OK (200) being the HTTP response code
        }
        else
        {
            // Set the response and exit
            $this->response([
                'status' => FALSE,
                'message' => 'No data were found'
            ], REST_Controller::HTTP_NOT_FOUND); // NOT_FOUND (404) being the HTTP response code
        }
    }

    /**
     * @api {post} api/projects Add New Project
     * @apiName PostProject
     * @apiGroup Projects
     *
     * @apiHeader {String} authtoken Authentication token, generated from admin area
     *
     * @apiParam {String} name                                  Mandatory Project Name.
     * @apiParam {string="lead","customer","internal"} rel_type Mandatory Project Related.
     * @apiParam {Number} clientid                              Mandatory Related ID.
     * @apiParam {Number} billing_type                          Mandatory Billing Type.
     * @apiParam {Date} start_date                              Mandatory Project Start Date.
     * @apiParam {Number} status                                Mandatory Project Status.
     * @apiParam {String} [progress_from_tasks]                 Optional on or off progress from tasks.
     * @apiParam {String} [project_cost]                        Optional Project Cost.
     * @apiParam {String} [progress]                            Optional project progress.
     * @apiParam {String} [project_rate_per_hour]               Optional project rate per hour.
     * @apiParam {String} [estimated_hours]                     Optional Project estimated hours.
     * @apiParam {Number[]} [project_members]                   Optional Project members.
     * @apiParam {Date} [deadline]                              Optional Project deadline.
     * @apiParam {String} [tags]                                Optional Project tags.
     * @apiParam {String} [description]                         Optional Project description.
     *
     * @apiParamExample {Multipart Form} Request-Example:
     *     array (size=15)
     *        'name' => string 'Project Name' (length=12)
     *        'rel_type' => string 'customer' (length=8)
     *        'clientid' => string '3' (length=1)
     *        'progress_from_tasks' => string 'on' (length=2)
     *        'progress' => string '0' (length=1)
     *        'billing_type' => string '3' (length=1)
     *        'status' => string '2' (length=1)
     *        'project_cost' => string '' (length=0)
     *        'project_rate_per_hour' => string '' (length=0)
     *        'estimated_hours' => string '' (length=0)
     *        'project_members' => 
     *          array (size=1)
     *            0 => string '1' (length=1)
     *        'start_date' => string '25/07/2019' (length=10)
     *        'deadline' => string '' (length=0)
     *        'tags' => string '' (length=0)
     *        'description' => string '' (length=0)
     *
     *
     * @apiSuccess {Boolean} status Request status.
     * @apiSuccess {String} message Project add successful.
     *
     * @apiSuccessExample Success-Response:
     *     HTTP/1.1 200 OK
     *     {
     *       "status": true,
     *       "message": "Project add successful."
     *     }
     *
     * @apiError {Boolean} status Request status.
     * @apiError {String} message Project add fail.
     *
     * @apiErrorExample Error-Response:
     *     HTTP/1.1 404 Not Found
     *     {
     *       "status": false,
     *       "message": "Project add fail."
     *     }
     * 
     */
    public function data_post()
    {
        \modules\api\core\Apiinit::the_da_vinci_code('api');
        
        // form validation
        $this->form_validation->set_rules('name', 'Project Name', 'trim|required|max_length[600]', array('is_unique' => 'This %s already exists please enter another Project Name'));
        //$this->form_validation->set_rules('rel_type', 'Related', 'trim|required', array('is_unique' => 'This %s already exists please enter another Project Related'));
        $this->form_validation->set_rules('billing_type', 'Billing Type', 'trim|required', array('is_unique' => 'This %s already exists please enter another Project Billing Type'));
        $this->form_validation->set_rules('start_date', 'Project Start Date', 'trim|required', array('is_unique' => 'This %s already exists please enter another Project Start Date'));
        $this->form_validation->set_rules('status', 'Project Status', 'trim|required', array('is_unique' => 'This %s already exists please enter another Project Status'));
        $related = $this->input->post('rel_type', TRUE);
        $this->form_validation->set_rules('clientid', ucwords($related), 'trim|required|max_length[11]', array('is_unique' => 'This %s already exists please enter another Project Name'));
        
        if ($this->form_validation->run() == FALSE)
        {
            // form validation error
            $message = array(
                'status' => FALSE,
                'error' => $this->form_validation->error_array(),
                'message' => validation_errors() 
            );
            $this->response($message, REST_Controller::HTTP_NOT_FOUND);
        }
        else
        {
            $project_members = $this->Api_model->value($this->input->post('project_members', TRUE));
            $insert_data = [
                'name' => $this->input->post('name', TRUE),
                //'rel_type' => $this->input->post('rel_type', TRUE),
                'clientid' => $this->input->post('clientid', TRUE),
                'billing_type' => $this->input->post('billing_type', TRUE),
                'start_date' => $this->input->post('start_date', TRUE),
                'status' => $this->input->post('status', TRUE),
                'project_cost' => $this->Api_model->value($this->input->post('project_cost', TRUE)),
                'estimated_hours' => $this->Api_model->value($this->input->post('estimated_hours', TRUE)),
                'progress_from_tasks' => $this->Api_model->value($this->input->post('progress_from_tasks', TRUE)),
                'progress' => $this->Api_model->value($this->input->post('progress', TRUE)),
                'project_rate_per_hour' => $this->Api_model->value($this->input->post('project_rate_per_hour', TRUE)),
                'deadline' => $this->Api_model->value($this->input->post('deadline', TRUE)),
                'description' => $this->Api_model->value($this->input->post('description', TRUE)),
                'tags' => $this->Api_model->value($this->input->post('tags', TRUE)),
                
                'settings' => array( 'available_features' => array( 'project_overview', 'project_milestones', 'project_gantt', 'project_tasks', 'project_estimates', 'project_subscriptions', 'project_invoices', 'project_expenses', 'project_credit_notes', 'project_tickets', 'project_timesheets', 'project_files', 'project_discussions', 'project_notes', 'project_activity'))
            ];
            if ($project_members != '') {
                $insert_data['project_members'] = $project_members;
            }
            if (!empty($this->input->post('custom_fields', TRUE))) {
                $insert_data['custom_fields'] = $this->Api_model->value($this->input->post('custom_fields', TRUE));
            }

            // insert data
			$this->load->model('projects_model');
			$output = $this->projects_model->add($insert_data);
			if ($output > 0 && !empty($output)) {
				handle_project_file_uploads($output);
				// success
				$message = array(
					'status' => TRUE,
					'message' => 'Project add successful.',
					'record_id' => $output  // επιστρέφουμε το ID του νέου project
				);
				$this->response($message, REST_Controller::HTTP_OK);
			}

             else {
                // error
                $message = array(
                    'status' => FALSE,
                    'message' => 'Project add failed.'
                );
                $this->response($message, REST_Controller::HTTP_NOT_FOUND);
            }
        }
    }

    /**
     * @api {delete} api/delete/projects/:id Delete a Project
     * @apiName DeleteProject
     * @apiGroup Projects
     *
     * @apiHeader {String} authtoken Authentication token, generated from admin area
     *
     * @apiParam {Number} id project unique ID.
     *
     * @apiSuccess {Boolean} status Request status.
     * @apiSuccess {String} message Project Delete successful.
     *
     * @apiSuccessExample Success-Response:
     *     HTTP/1.1 200 OK
     *     {
     *       "status": true,
     *       "message": "Project Delete Successful."
     *     }
     *
     * @apiError {Boolean} status Request status.
     * @apiError {String} message Project Delete Fail.
     *
     * @apiErrorExample Error-Response:
     *     HTTP/1.1 404 Not Found
     *     {
     *       "status": false,
     *       "message": "Project Delete Fail."
     *     }
     */
    public function data_delete($id = '')
    {
        $id = $this->security->xss_clean($id);
        if (empty($id) && !is_numeric($id))
        {
            $message = array(
                'status' => FALSE,
                'message' => 'Invalid Project ID'
            );
            $this->response($message, REST_Controller::HTTP_NOT_FOUND);
        }
        else
        {
            // delete data
            $this->load->model('projects_model');
            $output = $this->projects_model->delete($id);
            if ($output === TRUE) {
                // success
                $message = array(
                    'status' => TRUE,
                    'message' => 'Project Delete Successful.'
                );
                $this->response($message, REST_Controller::HTTP_OK);
            } else {
                // error
                $message = array(
                    'status' => FALSE,
                    'message' => 'Project Delete Fail.'
                );
                $this->response($message, REST_Controller::HTTP_NOT_FOUND);
            }
        }
    }

    /**
     * @api {put} api/projects/:id Update a project
     * @apiName PutProject
     * @apiGroup Projects
     *
     * @apiHeader {String} authtoken Authentication token, generated from admin area
     *
     * @apiParam {String} name                                  Mandatory Project Name.
     * @apiParam {string="lead","customer","internal"} rel_type Mandatory Project Related.
     * @apiParam {Number} clientid                              Mandatory Related ID.
     * @apiParam {Number} billing_type                          Mandatory Billing Type.
     * @apiParam {Date} start_date                              Mandatory Project Start Date.
     * @apiParam {Number} status                                Mandatory Project Status.
     * @apiParam {String} [progress_from_tasks]                 Optional on or off progress from tasks.
     * @apiParam {String} [project_cost]                        Optional Project Cost.
     * @apiParam {String} [progress]                            Optional project progress.
     * @apiParam {String} [project_rate_per_hour]               Optional project rate per hour.
     * @apiParam {String} [estimated_hours]                     Optional Project estimated hours.
     * @apiParam {Number[]} [project_members]                   Optional Project members.
     * @apiParam {Date} [deadline]                              Optional Project deadline.
     * @apiParam {String} [tags]                                Optional Project tags.
     * @apiParam {String} [description]                         Optional Project description.
     *
     *
     * @apiParamExample {json} Request-Example:
     *  {
     *     "name": "Test1",
     *     "rel_type": "lead",
     *     "clientid": "9",
     *     "status": "2",
     *     "progress_from_tasks": "on",
     *     "progress": "0.00", 
     *     "billing_type": "3",
     *     "project_cost": "0",
     *     "project_rate_per_hour": "0",
     *     "estimated_hours": "0",
     *     "project_members":
     *      {
     *          "0": "5"
     *      }
     *     "start_date": "19/04/2019",
     *     "deadline": "30/08/2019",
     *     "tags": "",
     *     "description": "",
     *     "settings": 
     *       {
     *         "available_features":
     *           {
     *            "0": "project_overview",
     *             "1": "project_milestones" ,
     *             "2": "project_gantt" ,
     *             "3": "project_tasks" ,
     *             "4": "project_estimates" ,
     *             "5": "project_credit_notes" ,
     *             "6": "project_invoices" ,
     *             "7": "project_expenses",
     *             "8": "project_subscriptions" ,
     *             "9": "project_activity" ,
     *             "10": "project_tickets" ,
     *             "11": "project_timesheets",
     *             "12": "project_files" ,
     *             "13": "project_discussions" ,
     *             "14": "project_notes" 
     *          }
     *      }
     *  }
     *
     * @apiSuccess {Boolean} status Request status.
     * @apiSuccess {String} message Project Update Successful.
     *
     * @apiSuccessExample Success-Response:
     *     HTTP/1.1 200 OK
     *     {
     *       "status": true,
     *       "message": "Project Update Successful."
     *     }
     *
     * @apiError {Boolean} status Request status.
     * @apiError {String} message Project Update Fail.
     *
     * @apiErrorExample Error-Response:
     *     HTTP/1.1 404 Not Found
     *     {
     *       "status": false,
     *       "message": "Project Update Fail."
     *     }
     */
    public function data_put($id = '')
    {
        // JSON data is now automatically parsed in REST_Controller
        if (empty($_POST) || !isset($_POST)) {
            $this->load->library('parse_input_stream');
            $_POST = $this->parse_input_stream->parse_parameters();
            $_FILES = $this->parse_input_stream->parse_files();
            if (empty($_POST) || !isset($_POST)) {
                $message = array('status' => FALSE, 'message' => 'Data Not Acceptable OR Not Provided');
                $this->response($message, REST_Controller::HTTP_NOT_ACCEPTABLE);
            }
        }
        if (empty($id) && !is_numeric($id)) {
            $message = array('status' => FALSE, 'message' => 'Invalid Lead ID');
            $this->response($message, REST_Controller::HTTP_NOT_FOUND);
        } else {
            $update_data = $this->input->post();
            $update_file = isset($update_data['file']) ? $update_data['file'] : null;
            unset($update_data['file']);
            // update data
            $this->load->model('projects_model');
            $output = $this->projects_model->update($update_data, $id);
            if (!empty($update_file) && count($update_file)) {
                if ($output <= 0 || empty($output)) {
                    $output = $id;
                }
            }

            if ($output == true && !empty($output)) {
                // success
                $attachments = $this->projects_model->get_files($output);
                foreach ($attachments as $attachment) {
                    $this->projects_model->remove_file($attachment['id']);
                }
                $this->handle_project_attachments_array($output);
                $message = array(
                    'status' => TRUE,
                    'message' => 'Project Update Successful.'
                );
                $this->response($message, REST_Controller::HTTP_OK);
            } else {
                // error
                $message = array(
                    'status' => FALSE,
                    'message' => 'Project Update Fail.'
                );
                $this->response($message, REST_Controller::HTTP_NOT_FOUND);
            }
        }
    }

    function handle_project_attachments_array($project_id)
    {
        $hookData = hooks()->apply_filters('before_handle_project_file_uploads', [
            'project_id' => $project_id,
            'index_name' => 'file',
            'handled_externally' => false, // e.g. module upload to s3
            'handled_externally_successfully' => false,
            'files' => $_FILES
        ]);
    
        if ($hookData['handled_externally']) {
            return $hookData['handled_externally_successfully'];
        }
    
        $filesIDS = [];
        $errors   = [];
    
        if (isset($_FILES['file']['name'])
            && ($_FILES['file']['name'] != '' || is_array($_FILES['file']['name']) && count($_FILES['file']['name']) > 0)) {
            hooks()->do_action('before_upload_project_attachment', $project_id);
    
            if (!is_array($_FILES['file']['name'])) {
                $_FILES['file']['name']     = [$_FILES['file']['name']];
                $_FILES['file']['type']     = [$_FILES['file']['type']];
                $_FILES['file']['tmp_name'] = [$_FILES['file']['tmp_name']];
                $_FILES['file']['error']    = [$_FILES['file']['error']];
                $_FILES['file']['size']     = [$_FILES['file']['size']];
            }
    
            $path = get_upload_path_by_type('project') . $project_id . '/';
    
            for ($i = 0; $i < count($_FILES['file']['name']); $i++) {
                if (_perfex_upload_error($_FILES['file']['error'][$i])) {
                    $errors[$_FILES['file']['name'][$i]] = _perfex_upload_error($_FILES['file']['error'][$i]);
    
                    continue;
                }
    
                // Get the temp file path
                $tmpFilePath = $_FILES['file']['tmp_name'][$i];
                // Make sure we have a filepath
                if (!empty($tmpFilePath) && $tmpFilePath != '') {
                    _maybe_create_upload_path($path);
                    $originalFilename = unique_filename($path, $_FILES['file']['name'][$i]);
                    $filename = app_generate_hash() . '.' . get_file_extension($originalFilename);
    
                    // In case client side validation is bypassed
                    if (!_upload_extension_allowed($filename)) {
                        continue;
                    }
    
                    $newFilePath = $path . $filename;
                    // Upload the file into the company uploads dir
                    if (copy($tmpFilePath, $newFilePath)) {
                        unlink($tmpFilePath);
                        if (is_client_logged_in()) {
                            $contact_id = get_contact_user_id();
                            $staffid    = 0;
                        } else {
                            $staffid    = get_staff_user_id();
                            $contact_id = 0;
                        }
                        $data = [
                            'project_id' => $project_id,
                            'file_name'  => $filename,
                            'original_file_name'  => $originalFilename,
                            'filetype'   => $_FILES['file']['type'][$i],
                            'dateadded'  => date('Y-m-d H:i:s'),
                            'staffid'    => $staffid,
                            'contact_id' => $contact_id,
                            'subject'    => $originalFilename,
                        ];
                        if (is_client_logged_in()) {
                            $data['visible_to_customer'] = 1;
                        } else {
                            $data['visible_to_customer'] = ($this->input->post('visible_to_customer') == 'true' ? 1 : 0);
                        }
                        $this->db->insert(db_prefix() . 'project_files', $data);
    
                        $insert_id = $this->db->insert_id();
                        if ($insert_id) {
                            if (is_image($newFilePath)) {
                                create_img_thumb($path, $filename);
                            }
                            array_push($filesIDS, $insert_id);
                        } else {
                            unlink($newFilePath);
    
                            return false;
                        }
                    }
                }
            }
        }
    
        if (count($filesIDS) > 0) {
            $this->load->model('projects_model');
            end($filesIDS);
            $lastFileID = key($filesIDS);
            $this->projects_model->new_project_file_notification($filesIDS[$lastFileID], $project_id);
        }
    
        if (count($errors) > 0) {
            $message = '';
            foreach ($errors as $filename => $error_message) {
                $message .= $filename . ' - ' . $error_message . '<br />';
            }
            header('HTTP/1.0 400 Bad error');
            echo $message;
            die;
        }
    
        if (count($filesIDS) > 0) {
            return true;
        }
    
        return false;
    }
}