<?php
/**
 * @package    Proxim
 * @author     Mike Kivu <mikepaul620@gmail.com | https://webexpert.co.ke>
 * @copyright  2019 Proxim
 * @version    1.5.0
 * @since      File available since Release 1.0.0
 */

namespace Proxim\Api;

use Db;
use Exception;
use ZipArchive;
use Proxim\Database\DbQuery;
use Proxim\Configuration;
use Proxim\Mail;
use Proxim\Tools;
use Proxim\Validate;
use Proxim\Controller;
use Proxim\Order\Order;
use Proxim\Order\File;
use Proxim\User\Customer;
use Proxim\User\Employee;
use Proxim\Util\ArrayUtils;
use Proxim\Util\DateUtils;
use Proxim\Crypto\Hashing;
use Proxim\Module\Module;
use Proxim\Uploader;
use Proxim\Util\StringUtils;

class Modules extends Controller {
    public function doAction() {
        $app = $this->app;
        $payload = $app->request->post();
        $user = $app->container->user;

        $do = ArrayUtils::get($payload, 'do');
        $module_name = ArrayUtils::get($payload, 'module_name');

        switch($do) {
            case 'install':
                $module = Module::getInstanceByName($module_name);
                if (!$module) {
	                return $this->modal("ERROR", "Installation Failed", "Cannot install this module.");
                }

                try {
                    $module->install();
                    return $this->response([
                        "success" => true
                    ]);
                } catch(Exception $e) {
	                return $this->modal("ERROR", "Installation Failed", $e->getMessage());
                }
                break;

            case 'uninstall':
                $module = Module::getInstanceByName($module_name);
                if (!Validate::isLoadedObject($module)) {
	                return $this->modal("ERROR", "Uninstall Failed", "Cannot uninstall this module.");
                }

                try {
                    $module->uninstall();
                    return $this->response([
                        "success" => true
                    ]);
                } catch(Exception $e) {
	                return $this->modal("ERROR", "Uninstall Failed", $e->getMessage());
                }
                break;

            case 'activate':
                $module = Module::getInstanceByName($module_name);
                if (!$module) {
	                return $this->modal("ERROR", "Installation Failed", "Cannot install this module.");
                }

                $activation_key = ArrayUtils::get($payload, 'activation_key');
                if(!$activation_key) {
                    return $this->response([
                        "error" => true,
                        "message" => "Enter the activation key"
                    ]);
                }

                $activation_link = Module::$purchase_link . "/verify.php?" . http_build_query([
                    'domain' => $app->request->getHost(),
                    'module' => $module->name,
                    'activation_key' => $activation_key
                ]);

                $ch = curl_init();
                curl_setopt ($ch, CURLOPT_URL, $activation_link);
                curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
                curl_setopt($ch,  CURLOPT_USERAGENT , "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1)");
                curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, 0);
                $result = curl_exec($ch);
                curl_close($ch);
                $result = Tools::jsonDecode($result, true);

                if(isset($result['error'])) {
                    return $this->response([
                        "error" => true,
                        "message" => "Enter a valid activation key"
                    ]);
                }

                try {
                    
                    $module->install();
                    return $this->response([
                        'callback' => 'window.location.reload();'
                    ]);

                } catch(Exception $e) {
	                return $this->modal("ERROR", "Installation Failed", $e->getMessage());
                }
                break;

            case 'update':
                return $this->response([
                    "success" => true
                ]);
                break;

            default:
                return $this->response([
                    "error" => true,
                    "message" => "Error 404. Resource not found"
                ]);
                break;
        }
        
    }

    public function uploadPlugin() {
        $app = $this->app;
        $payload = $app->request->post();
        $user = $app->container->user;

        $files = ArrayUtils::get($payload, 'files');
		if (!is_array($files) || empty($files)) {
            return $this->response([
                'error' => true,
                'message' => "Select the modules to upload"
            ]);
        }


		foreach ($files as $module_file) {
            $file = PROX_DIR_UPLOADS . $module_file['newName']; 
            $tmp_folder = PROX_DIR_MODULE . md5(time());
            $zip_folders = array();

            $success = false;
            if (substr($file, -4) == '.zip') {
                if (Tools::ZipExtract($file, $tmp_folder)) {
                    $zip_folders = scandir($tmp_folder, SCANDIR_SORT_NONE);
                    if (Tools::ZipExtract($file, PROX_DIR_MODULE)) {
                        $success = true;
                    }
                }
            } else {
                $archive = new \Archive_Tar($file);
                if ($archive->extract($tmp_folder)) {
                    $zip_folders = scandir($tmp_folder, SCANDIR_SORT_NONE);
                    if ($archive->extract(PROX_DIR_MODULE)) {
                        $success = true;
                    }
                }
            }

            if (!$success) {
                return $this->response([
                    'error' => true,
                    'message' => "There was an error while extracting the module (file may be corrupted)."
                ]);
            } else {
                //check if it's a real module
                foreach ($zip_folders as $folder) {
                    if (!in_array($folder, array('.', '..', '.svn', '.git', '__MACOSX')) && !Module::getInstanceByName($folder)) {
                        $this->recursiveDeleteOnDisk(PROX_DIR_MODULE . $folder);
                        return $this->response([
                            'error' => true,
                            'message' => sprintf('The module %1$s that you uploaded is not a valid module.', $folder)
                        ]);
                    }
                }
            }

            @unlink($file);
            $this->recursiveDeleteOnDisk($tmp_folder);

            return $this->response([
                'callback' => 'window.location.reload();'
            ]);
        }
    }

    protected function recursiveDeleteOnDisk($dir)
    {
        if (strpos(realpath($dir), realpath(PROX_DIR_MODULE)) === false) {
            return;
        }
        if (is_dir($dir)) {
            $objects = scandir($dir, SCANDIR_SORT_NONE);
            foreach ($objects as $object) {
                if ($object != '.' && $object != '..') {
                    if (filetype($dir . '/' . $object) == 'dir') {
                        $this->recursiveDeleteOnDisk($dir . '/' . $object);
                    } else {
                        unlink($dir . '/' . $object);
                    }
                }
            }
            reset($objects);
            rmdir($dir);
        }
    }
}