<?php

class DefaultController extends Controller
{

    /**
     * @var string the default layout for the views. Defaults to '//layouts/column2', meaning
     * using two-column layout. See 'protected/views/layouts/column2.php'.
     */
    public $layout = '//layouts/column2';

    /**
     * @return array action filters
     */
    public function filters()
    {
        return array(
            'accessControl', // perform access control for CRUD operations
        );
    }

    /**
     * Specifies the access control rules.
     * This method is used by the 'accessControl' filter.
     * @return array access control rules
     */
    public function accessRules()
    {
        return array(
            array('allow', // allow all users to perform 'index' and 'view' actions
                'actions' => array('index', 'create', 'delete', 'download', 'deleteBackup', 'restore', 'uploadBackup', 'factoryResetPhonalisa', "chunkedUpload"),
                'expression' => AccessManager::checkSessionPermission($this->module->name),
            ),
            array('deny', // deny all users
                'users' => array('*'),
            ),
        );
    }
    
    public function actionChunkedUpload()
    {
        try{ 
            if (!empty($_FILES)) {
                foreach ($_FILES as $file)
                {
                    $appendToFile = true;
                    if ($_POST['resumableChunkNumber'] === "1") {
                        $oldBackups = PhonalisaDBConnector::getBackups();
                        if (property_exists($oldBackups, "data") && property_exists($oldBackups->data, $file['name'])) {
                            throw new CHttpException(500, __("UPLOAD_ERROR_FILE_ALREADY_EXISTS"));
                        }
                        $appendToFile = false;
                    }
                    $chunkToStore = file_get_contents($file["tmp_name"]);
                    $result = PhonalisaDBConnector::storeBackupData($file['name'], $chunkToStore, strlen($chunkToStore), $appendToFile);
                    if ( $result->status !== "ok") {
                        throw new CHttpException(500, $result->reason);
                    }
                }
            }
        } catch (Exception $err) {
            $this->throwChunkUploadError($err->getMessage(), $err->statusCode);
        }
    }
    
    private function throwChunkUploadError($message, $statusCode = 500)
    {
        header("HTTP/1.0 $statusCode $message");
        echo json_encode(array("status" => $statusCode, "message" => $message));
    }

    /**
     * Lists all models.
     */
    public function actionIndex()
    {
        $model = new Backup();
        $model->unsetAttributes();  // clear any default values
        if (isset($_GET['Backup'])) {
            $model->attributes = $_GET['Backup'];
        }
        $this->render('index', array('model' => $model));
    }

    public function actionCreate()
    {
        $model = new Backup();
        $this->performAjaxValidation($model);
        
        if (isset($_REQUEST['Backup']['comment'])) {
            $result = PhonalisaDBConnector::createBackup($_REQUEST['Backup']['comment']);
            if ($result->status === 'ok') {
                Yii::app()->user->setFlash('success', '<strong>' . __('SYSTEM_BACKUP_RESTORE_CREATE_SUCCESS') . '</strong>');
            } else {
                Yii::app()->user->setFlash('error', '<strong>ERROR: ' . $result->reason . '</strong>');
            }
        }
        $this->renderPartial('_create', array('model'=>$model), false, true);
    }

    /**
     * Deletes a particular model.
     * If deletion is successful, the browser will be redirected to the 'admin' page.
     * @param integer $id the ID of the model to be deleted
     */
    public function actionDelete($id)
    {
        if (Yii::app()->request->isPostRequest) {
            $this->loadModel($id)->delete();

            // if AJAX request (triggered by deletion via admin grid view), we should not redirect the browser
            if (!isset($_GET['ajax'])) {
                $this->redirect(isset($_POST['returnUrl']) ? $_POST['returnUrl'] : array('admin'));
            }
        } else {
            throw new CHttpException(400, 'Invalid request. Please do not repeat this request again.');
        }
    }

    public function actionDownload()
    {
        if (isset($_REQUEST['fileName'])) {
            $fileName = $_REQUEST['fileName'];
            $limit = 1024 * 1024; // 1MByte
            $offset = 0;
            $result = PhonalisaDBConnector::getBackupData($fileName, $bin, $length, $limit, $offset);
            $this->printHeaderForFileDownload($fileName, $result->filesize);
            do {
                $offset += $length;
                echo $bin;
                PhonalisaDBConnector::getBackupData($fileName, $bin, $length, $limit, $offset);
            } while ($length != 0);
        }
    }

    protected function printHeaderForFileDownload($fileName, $length)
    {
        header('Content-type: application/octet-stream');
        header("Content-length: $length");
        header("Content-disposition: attachment; filename=$fileName");
        header("Pragma: no-cache");
        header("Expires: 0");
    }

    public function actionDeleteBackup()
    {
        if (isset($_REQUEST['fileName'])) {
            $fileName = $_REQUEST['fileName'];
            PhonalisaDBConnector::deleteBackup($fileName);
        }
    }

    public function actionRestore()
    {
        if (isset($_REQUEST['file_name'])) {
            $fileName = $_REQUEST['file_name'];
            PhonalisaDBConnector::restoreBackup($fileName);
            removeDirectoryRecursive(Yii::app()->runtimePath);
            $statusMsg = 'ok';
            echo json_encode($statusMsg);
            Yii::app()->end();
        }
    }

    public function actionUploadBackup()
    {
        if (isset($_FILES['BackupFile'])) {

            if ($_FILES['BackupFile']['error'] === UPLOAD_ERR_NO_FILE) {
                Yii::app()->user->setFlash('error', '<strong>ERROR: ' . __('SYSTEM_BACKUP_RESTORE_ERROR_MESSAGE_NO_FILE') . '</strong>');
                $this->redirect(url('/systemBackupRestore'));
            }

            $realFileName = $_FILES['BackupFile']['name'];
            $tmpFileName = $_FILES['BackupFile']['tmp_name'];
            $length = $_FILES['BackupFile']['size'];

            $result = $this->storeFileDataToDB($tmpFileName, $realFileName);

            if ($result != FALSE && $result->status === 'ok') {
                Yii::app()->user->setFlash('success', '<strong>' . __('SYSTEM_BACKUP_RESTORE_UPLOAD_SUCCESS') . '</strong>');
                $this->redirect(url('/systemBackupRestore'));
            } else {
                Yii::app()->user->setFlash('error', '<strong>ERROR: ' . $result->reason . '</strong>');
                $this->redirect(url('/systemBackupRestore'));
            }
        }
        $this->renderPartial('_uploadBackup', array(), false, true);
    }

    public function storeFileDataToDB($tmpFileName, $realFileName)
    {
        $fh = fopen($tmpFileName, "rb");
        $result = FALSE;
        if ($fh == FALSE) {
            return FALSE;
        }

        $appendToFile = false;
        while (!feof($fh)) {
            $length = 1024 * 1024;
            $chunkToStore = fread($fh, $length);
            $result = PhonalisaDBConnector::storeBackupData($realFileName, $chunkToStore, strlen($chunkToStore), $appendToFile);
            if ($result->status != 'ok') {
                return $result;
            }
            $appendToFile = true;
        }
        return $result;
    }

    public function actionFactoryResetPhonalisa()
    {
        if (app()->params->applianceMode && app()->params->applianceModel != "debian") {
            PhonalisaCtrldConnector::runFactoryReset();
        } else {
            PhonalisaDBConnector::resetDatabase();
        }

        removeDirectoryRecursive(Yii::app()->runtimePath);
        $message = '';

        if (app()->params->applianceMode) {
            $message = 'ok';
            Yii::app()->user->logout();
        }
        
        echo json_encode($message);

        if (app()->params->applianceMode && app()->params->applianceModel == "debian") {
            PhonalisaCtrldConnector::rebootSystem();
        }        
        
        Yii::app()->end();
    }

    /**
     * Returns the data model based on the primary key given in the GET variable.
     * If the data model is not found, an HTTP exception will be raised.
     * @param integer the ID of the model to be loaded
     */
    public function loadModel($id)
    {
        $model = Backup::model()->findByPk($id);
        if ($model === null) {
            throw new CHttpException(404, 'The requested page does not exist.');
        }
        return $model;
    }

    /**
     * Performs the AJAX validation.
     * @param CModel the model to be validated
     */
    protected function performAjaxValidation($model)
    {
        if (isset($_POST['ajax']) && $_POST['ajax'] === 'backup-form') {
            echo CActiveForm::validate($model);
            Yii::app()->end();
        }
    }
}
