<?php

namespace TdyCommons\Controller\Rest;

use TdyCommons\Controller\BaseRestController;
use TdyCommons\Model\Setting;
use Zend\Filter\File\RenameUpload;
use Zend\View\Model\JsonModel;

class SettingsController extends BaseRestController
{

    /**
     * @see BaseApiController::identifierName
     *
     * @var string
     */
    protected $identifierName = 'id';

    /**
     * @see      BaseApiController::getList()
     *
     * @api      {get} /settings List Settings
     * @apiName  Get Settings
     * @apiGroup Settings
     *
     * @apiParam {String} [q=] Keyword to search.
     * @apiParam {Number} [p=1] Page number.
     * @apiParam {Number} [l=20] Number of settings to display at a time.
     * @apiparam {Array}  [f=] Field filtering.
     * @apiparam {Array}  [s=] Field sorting.
     *
     * @apiSuccess (200 OK) {Object}   httpStatus HTTP status code.
     * @apiSuccess (200 OK) {Object[]} data    List of Settings.
     *
     * @return JsonModel
     */
    public function getList()
    {
        $q = $this->params()->fromQuery('q', '');
        $p = (int) $this->params()->fromQuery('p', 1);
        $l = (int) $this->params()->fromQuery('l', $this->getSettingsTable()->get('items-per-page'));
        $s = $this->params()->fromQuery('s', []);
        $f = $this->params()->fromQuery('f', []);

        $paginable = $l > 0;

        $resultSet = $this->getSettingsTable()->fetch($q, $f, $s, $paginable);

        if ($paginable) {
            $resultSet->setCurrentPageNumber((int) $p);
            $resultSet->setItemCountPerPage($l);
        }

        if ($p > 0 && $l > 0) {
            $i = (($p - 1) * $l);
        } else {
            $i = 0;
        }

        $settings = iterator_to_array($resultSet);

        /**
         * @var int     $k
         * @var Setting $setting
         */
        foreach ($settings as $k => $setting) {
            $setting->rowNo = ++ $i;
            $settings[ $k ] = $setting->toStdClass();
        }

        return $this->statusOk([
            'entries'    => $settings,
            'pagination' => [
                'pageNumber' => $p,
                'pageSize'   => $paginable ? $l : 1,
                'totalItems' => $paginable ? $resultSet->getTotalItemCount() : count($settings),
                'totalPages' => $paginable ? $resultSet->count() : count($settings),
            ],

        ]);
    }

    /**
     * @api      {get} /settings/:id Get Setting
     * @apiName  Get Settings
     * @apiGroup Settings
     *
     * @apiParam {Number} id The Setting ID.
     *
     * @apiSuccess (200 OK) {Object}  httpStatus HTTP status code.
     * @apiSuccess (200 OK) {Object}  data    Returns the Setting.
     *
     * @param int $id
     *
     * @return JsonModel
     */
    public function get($id)
    {
        $setting = $this->getSettingsTable()->get($id);

        return $this->statusOk([
            'entry'      => $setting->toStdClass(),
            'pagination' => [
                'pageNumber' => 1,
                'pageSize'   => 1,
                'totalItems' => 1,
                'totalPages' => 1,
            ],
        ]);
    }

    /**
     * @api        {post} /settings Create New Setting
     * @apiVersion 0.0.1
     * @apiName    Post Setting
     * @apiGroup   Settings
     *
     * @apiSuccess (200 OK) {Object}  httpStatus HTTP status code.
     * @apiSuccess (200 OK) {Object}  data    Returns the Setting object.
     *
     * @param array $data
     *
     * @return JsonModel
     */
    public function create($data)
    {
        $httpRequest      = $this->getRequest();
        $contentTypeValue = $httpRequest->getHeaders()->get('Content-Type')->getFieldValue();

        list($contentType) = explode(';', trim($contentTypeValue));

        switch ($contentType) {
            case 'multipart/form-data':
                $file   = $httpRequest->getFiles('file');
                $filter = new RenameUpload([
                    'target'    => APP_ROOT_PATH . "/app/data/uploads/sheet.upd",
                    'randomize' => true,
                ]);

                $file = $filter->filter($file);
                $path = $file['tmp_name'];

                $valid  = false;
                $reader = null;
                $types  = ['Excel2007', 'Excel5', 'CSV'];
                foreach ($types as $type) {
                    $reader = \PHPExcel_IOFactory::createReader($type);
                    if ($reader->canRead($path)) {
                        $valid = true;
                        break;
                    }
                }

                if ($valid) {
                    /** @var \PHPExcel $objPHPExcel */
                    $objPHPExcel = $reader->load($path);
                    $worksheet   = $objPHPExcel->getActiveSheet();

                    $i        = 1;
                    $j        = 1;
                    $settings = [];

                    foreach ($worksheet->getRowIterator() as $row) {
                        $cellIterator = $row->getCellIterator();
                        $cellIterator->setIterateOnlyExistingCells(false);

                        if ($i == 1 && $worksheet->getCell('A1')->getValue() == 'isoCode') {
                            $i ++;
                            continue;
                        }

                        $setting        = new Setting();
                        $setting->key   = $worksheet->getCell('A' . $i)->getValue();
                        $setting->value = $worksheet->getCell('B' . $i)->getValue();

                        $newObject        = $this->getSettingsTable()->save($setting);
                        $newObject->rowNo = $j;
                        $settings[]       = $newObject->toStdClass();

                        $i ++;
                        $j ++;
                    }

                    unlink($path);

                    return $this->statusOk([
                        'entries'    => $settings,
                        'pagination' => [
                            'pageNumber' => 1,
                            'pageSize'   => $i,
                            'totalItems' => $i,
                            'totalPages' => 1,
                        ],
                    ]);

                } else {
                    return $this->statusBadRequest([
                        'system'   => [
                            'id'          => 4002,
                            'description' => 'Invalid Import File'
                        ],
                        'settings' => [
                            'description' => 'The file for import is invalid. Only accepts files in CSV, XLS, or XLSX format.',
                        ]
                    ]);
                }

                break;
            case 'application/json':
            case 'text/json':
            default:
                $inputFilter = new SettingInputFilter();
                $inputFilter->setData($data);

                if ($inputFilter->isValid()) {
                    $data = $inputFilter->getValues();

                    $setting            = new Setting($data);
                    $setting->createdBy = $this->getCurrentUser()->id;

                    $setting = $this->getSettingsTable()->save($setting);

                    return $this->statusOk([
                        'entry'      => $setting->toStdClass(),
                        'pagination' => [
                            'pageNumber' => 1,
                            'pageSize'   => 1,
                            'totalItems' => 1,
                            'totalPages' => 1,
                        ],
                    ]);
                } else {
                    return $this->statusBadRequest([
                        'system'   => [
                            'id'          => 4001,
                            'description' => 'Invalid Request'
                        ],
                        'settings' => [
                            'description' => 'Submission is invalid.',
                            'details'     => $inputFilter->getMessages()
                        ]
                    ]);
                }
                break;
        }
    }

    /**
     * @api        {put} /settings/:id Update Setting
     * @apiVersion 0.0.1
     * @apiName    Put Setting
     * @apiGroup   Settings
     *
     * @apiSuccess (200 OK) {Object}  httpStatus HTTP status code.
     * @apiSuccess (200 OK) {Object}  data    Returns the Setting object.
     *
     * @param int   $cnt
     * @param array $data
     *
     * @return JsonModel
     */
    public function update($cnt, $data)
    {
        $inputFilter = new SettingInputFilter();
        $inputFilter->setData($data);

        if ($inputFilter->isValid()) {
            $setting            = new Setting($data);
            $setting->updatedBy = $this->getCurrentUser()->id;
            $setting            = $this->getSettingsTable()->save($setting);

            return $this->statusOk([
                'entry'      => $setting->toStdClass(),
                'pagination' => [
                    'pageNumber' => 1,
                    'pageSize'   => 1,
                    'totalItems' => 1,
                    'totalPages' => 1,
                ],
            ]);
        } else {
            return $this->statusBadRequest([
                'system'   => [
                    'id'          => 4001,
                    'description' => 'Invalid Request'
                ],
                'settings' => [
                    'description' => 'Submission is invalid.',
                    'details'     => $inputFilter->getMessages()
                ]
            ]);
        }
    }

    /**
     * @api        {delete} /settings/:id Delete Setting
     * @apiVersion 0.0.1
     * @apiName    Delete Setting
     * @apiGroup   Settings
     *
     * @apiSuccess (200 OK) {Object}  httpStatus HTTP status code.
     * @apiSuccess (200 OK) null      data
     *
     * @param int $cnt
     *
     * @return JsonModel
     */
    public function delete($cnt)
    {
        if ($cnt > 0) {
            $setting = $this->getSettingsTable()->get($cnt);
            if ($setting) {
                $setting->deletedBy = $this->getCurrentUser()->id;
                $this->getSettingsTable()->delete($setting);

                return $this->statusOk([
                    'entry'      => null,
                    'pagination' => [
                        'pageNumber' => 1,
                        'pageSize'   => 1,
                        'totalItems' => 1,
                        'totalPages' => 1,
                    ],
                ]);
            } else {
                return $this->statusNotFound();
            }
        } else {
            return $this->statusNotFound();
        }
    }

}
