<?php
/**
 * @author WebRotate 360 LLC
 * @copyright Copyright (C) 2023 WebRotate 360 LLC. All rights reserved.
 * @license GNU General Public License version 2 or later (http://www.gnu.org/copyleft/gpl.html).
 * @version 4.0
 * @module WebRotate 360 Product Viewer for Prestashop
 */

if (!defined('_PS_VERSION_'))
    exit;

class WebRotate360 extends Module
{
    private $admin_prodrec_saved = false;

    public function __construct()
    {
        $this->name                   = "webrotate360";
        $this->tab                    = "others";
        $this->version                = "4.0.0";
        $this->author                 = "WebRotate 360 LLC";
        $this->need_instance          = 0;
        $this->module_key             = "5503098f2a84ade86a4e1478fb8cded1";
        $this->bootstrap              = true;
        $this->ps_versions_compliancy = array('min' => '1.7', 'max' => _PS_VERSION_);

        parent::__construct();

        $this->displayName            = $this->l("WebRotate 360");
        $this->description            = $this->l("Integrates WebRotate 360 Product Viewer with PrestaShop product pages");
        $this->confirmUninstall       = $this->l('Are you sure you want to uninstall?');
    }

    public function install()
    {
        if (parent::install() == false ||
            !$this->registerHook("header") ||
            !$this->registerHook("actionFrontControllerSetMedia") ||
            !$this->registerHook("actionProductUpdate") ||
            !$this->registerHook("displayAdminProductsExtra")) {
            return false;
        }

        if (!Db::getInstance()->Execute(
            "CREATE TABLE IF NOT EXISTS `" . _DB_PREFIX_ . "webrotate360` (
            `id_view` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
            `id_product` INT UNSIGNED NOT NULL,
            `config_file_url` VARCHAR(2048) NOT NULL,
            `root_path` VARCHAR(2048) NOT NULL) ENGINE = " . _MYSQL_ENGINE_ . " DEFAULT CHARSET=utf8")) {
            return false;
        }

        Configuration::updateValue("wr360_placeholder",    ".product-cover");
        Configuration::updateValue("wr360_skin",           "basic");
        Configuration::updateValue("wr360_viewer_width",   "100%");
        Configuration::updateValue("wr360_viewer_height",  "500px");
        Configuration::updateValue("wr360_popup_skin",     "default");
        Configuration::updateValue("wr360_viewer_inpopup", "no");
        Configuration::updateValue("wr360_use_analytics",  "no");
        Configuration::updateValue("wr360_gallery_order",  "first");

        return true;
    }

    public function uninstall()
    {
        if (parent::uninstall() == false)
            return (false);

        return Db::getInstance()->Execute("DROP TABLE IF EXISTS `" . _DB_PREFIX_ . "webrotate360`;");
    }

    public function hookDisplayAdminProductsExtra($params)
    {
        $this->admin_prodrec_saved = false;
        $product_id = $params['id_product'];

        $web360_fetch = Db::getInstance()->ExecuteS(
            "SELECT config_file_url, root_path FROM " . _DB_PREFIX_ . "webrotate360 WHERE id_product = " . (int)$product_id);

        if (!empty($web360_fetch))
            $this->smarty->assign($web360_fetch[0]);

        $this->smarty->assign(array("demo_xml" => Context::getContext()->shop->getBaseURL(true) . 'modules/webrotate360/360assets/sampleshoe/sampleshoe.xml'));
        return $this->display(__FILE__, "webrotate360_admin_product.tpl");
    }

    public function hookActionProductUpdate($params)
    {
        if ($this->admin_prodrec_saved) {
            return;
        }

        $product_id = $params['id_product'];
        $config_url = Tools::getValue("config_file_url");
        $root_path  = Tools::getValue("root_path");

        $fetch = Db::getInstance()->ExecuteS("SELECT config_file_url, root_path FROM " . _DB_PREFIX_ . "webrotate360 WHERE id_product = " . (int)$product_id);

        if (empty($fetch)) {
            Db::getInstance()->insert("webrotate360",
                array("id_product" => (int)$product_id, "config_file_url" => pSQL($config_url), "root_path" => pSQL($root_path)));
        }
        else {
            Db::getInstance()->update("webrotate360",
                array("config_file_url" => pSQL($config_url), "root_path" => pSQL($root_path)), "id_product=" . (int)$product_id);
        }

        $this->admin_prodrec_saved = true;
    }

    public function hookHeader($params)
    {
        return $this->display(__FILE__, "webrotate360_header.tpl");
    }

    private function extractModuleSettings($product_id)
    {
        $config_file_url = "";
        $root_path = "";
		$popup_ref_hrf = "";

        $fetch = Db::getInstance()->ExecuteS("SELECT config_file_url, root_path FROM " . _DB_PREFIX_ . "webrotate360 WHERE id_product = " . (int)$product_id);

        if (!empty($fetch)) {
            $product_config  = $fetch[0];
            $root_path = $product_config["root_path"];
            $master_config = Configuration::get("wr360_master_config");
            $config_file_url = $product_config["config_file_url"];

            if (!empty($master_config) && empty($config_file_url))
                $config_file_url = $master_config;
        }

        if (empty($config_file_url)) {
            return null;
        }

        $use_analytics = Configuration::get("wr360_use_analytics") === "yes";
        $is_viewer_popup = Configuration::get("wr360_viewer_inpopup") === "yes";

        $viewer_skin = Configuration::get("wr360_skin");
        if (empty($viewer_skin)) {
            $viewer_skin = "basic";
        }

        $popup_skin = Configuration::get("wr360_popup_skin");
        if (empty($popup_skin)) {
            $popup_skin = "light_clean";
        }

        $gallery_order = Configuration::get("wr360_gallery_order");
        if (empty($gallery_order)) {
            $gallery_order = "first";
        }

        $viewer_width = Configuration::get("wr360_viewer_width");
        if (!empty($viewer_width)) {
            $viewer_width = str_ireplace("px", "", $viewer_width);
            if ((!$is_viewer_popup) && (strpos($viewer_width, "%") === FALSE))
                $viewer_width .= "px";
        }

        $viewer_height = Configuration::get("wr360_viewer_height");
        if (!empty($viewer_height)) {
            $viewer_height = str_ireplace("px", "", $viewer_height);
            if ((!$is_viewer_popup) && (strpos($viewer_height, "%") === FALSE))
                $viewer_height .= "px";
        }

        $base_width = Configuration::get("wr360_base_width");
        if (!empty($base_width)) {
            $base_width = preg_replace("/[^0-9]/", "", $base_width);
        }
        if (empty($base_width)) {
            $base_width = 0;
        }

        $min_height = Configuration::get("wr360_min_height");
        if (!empty($min_height)) {
            $min_height = preg_replace("/[^0-9]/", "", $min_height);
        }
        if (empty($min_height)) {
            $min_height = 0;
        }

        $license_path = Configuration::get("wr360_license");
        if (empty($license_path)) {
            $license_path = ($is_viewer_popup) ? "license.lic" : _MODULE_DIR_ . "webrotate360/license.lic";
        }

        if ($is_viewer_popup) {
            $popup_ref_fmt = '%s?config=%s&root=%s&height=%s&lic=%s&grphpath=%s&analyt=%s&iframe=true&width=%s&height=%s';

            $popup_ref_hrf = sprintf($popup_ref_fmt,
                _MODULE_DIR_ . "webrotate360/viewloader_" . $viewer_skin . ".html",
                urlencode($config_file_url),
                urlencode($root_path),
                $viewer_height,
                urlencode($license_path),
                urlencode("imagerotator/html/img/" . $viewer_skin),
                $use_analytics ? "true" : "false",
                str_ireplace("%", "", $viewer_width),
                $viewer_height);
        }

        $module_settings = array(
            "module_path"     => _MODULE_DIR_ . "webrotate360/",
            "license_path"    => $license_path,
            "graphics_path"   => _MODULE_DIR_ . "webrotate360/imagerotator/html/img/" . $viewer_skin,
            "placeholder"     => Configuration::get("wr360_placeholder"),
            "viewer_skin"     => $viewer_skin,
            "popup_skin"      => $popup_skin,
            "popup_href"      => $popup_ref_hrf,
            "popup_thumb"     => _MODULE_DIR_ . "webrotate360/360thumb.svg",
            "viewer_height"   => $viewer_height,
            "viewer_width"    => $viewer_width,
            "base_width"      => $base_width,
            "config_file_url" => $config_file_url,
            "root_path"       => $root_path,
            "is_viewer_popup" => $is_viewer_popup,
            "use_analytics"   => $use_analytics ? "true" : "false",
            "min_height"      => $min_height,
            "api_callback"    => Configuration::get("wr360_api_callback"),
            "gallery_order"   => $gallery_order
        );

        return $module_settings;
    }

    public function hookActionFrontControllerSetMedia($params)
    {
        if ($this->context->controller->php_self !== 'product') {
            return;
        }

        $product_id = Tools::getValue("id_product");
        if (empty($product_id)) {
            return;
        }

        $settings = $this->extractModuleSettings($product_id);
        if (empty($settings)) {
            return;
        }

        $this->smarty->assign(array(
            "webrotate360" => $settings,
            "webrotate360json" => json_encode($settings, JSON_UNESCAPED_SLASHES)));

        if (!$settings["is_viewer_popup"]) {
            $this->context->controller->registerStylesheet('webrotate360-skin-css',
                'modules/' . $this->name . '/imagerotator/html/css/' . $settings["viewer_skin"] . '.css', ['priority' => 200]);
            $this->context->controller->registerStylesheet('webrotate360-overrides-css',
                'modules/' . $this->name . '/webrotate_overrides.css', ['priority' => 200]);
            $this->context->controller->registerJavascript('prettyPhoto-js',
                'modules/' . $this->name . '/imagerotator/html/js/imagerotator.js', ['priority' => 200]);
        }
        else {
            $this->context->controller->registerStylesheet('prettyPhoto-css',
                'modules/' . $this->name . '/prettyphoto/css/prettyphoto.css', ['priority' => 200]);
            $this->context->controller->registerJavascript('prettyPhoto-js',
                'modules/' . $this->name . '/prettyphoto/js/jquery.prettyPhoto.js', ['priority' => 200]);
        }

        $this->context->controller->registerJavascript('webrotate360-hook-js',
            'modules/' . $this->name . '/webrotate_prestahook.js', ['priority' => 200]);
    }

    public function getContent()
    {
        $output = null;

        if (Tools::isSubmit("submit" . $this->name)) {
            $output .= $this->displayConfirmation($this->l("Settings updated"));

            Configuration::updateValue("wr360_placeholder",    Tools::getValue("wr360_placeholder"));
            Configuration::updateValue("wr360_master_config",  Tools::getValue("wr360_master_config"));
            Configuration::updateValue("wr360_theme",          Tools::getValue("wr360_theme"));
            Configuration::updateValue("wr360_viewer_width",   Tools::getValue("wr360_viewer_width"));
            Configuration::updateValue("wr360_viewer_height",  Tools::getValue("wr360_viewer_height"));
            Configuration::updateValue("wr360_base_width",     Tools::getValue("wr360_base_width"));
            Configuration::updateValue("wr360_skin",           Tools::getValue("wr360_skin"));
            Configuration::updateValue("wr360_popup_skin",     Tools::getValue("wr360_popup_skin"));
            Configuration::updateValue("wr360_viewer_inpopup", Tools::getValue("wr360_viewer_inpopup"));
            Configuration::updateValue("wr360_license",        Tools::getValue("wr360_license"));
            Configuration::updateValue("wr360_min_height",     Tools::getValue("wr360_min_height"));
            Configuration::updateValue("wr360_use_analytics",  Tools::getValue("wr360_use_analytics"));
            Configuration::updateValue("wr360_api_callback",   Tools::getValue("wr360_api_callback"));
            Configuration::updateValue("wr360_gallery_order",  Tools::getValue("wr360_gallery_order"));
        }

        return $output . $this->displayForm();
    }

    private function getYesNoArray()
    {
        $yesno = array("no", "yes");
        $yesno_fmt = array();
        foreach ($yesno as $flag) {
            $yesno_fmt[] = array("id" => $flag, "name" => $flag);
        }

        return $yesno_fmt;
    }

    private function getViewerSkinArray()
    {
        $viewer_skins = array("basic", "thin", "round", "retina", "empty", "zoom_light", "zoom_dark");
        $viewer_skins_fmt = array();
        foreach ($viewer_skins as $skin) {
            $viewer_skins_fmt[] = array("id" => $skin, "name" => $skin);
        }

        return $viewer_skins_fmt;
    }

    private function getGalleryOrder()
    {
        $positions = array("first", "last");
        $positions_fmt = array();
        foreach ($positions as $pos) {
            $positions_fmt[] = array("id" => $pos, "name" => $pos);
        }

        return $positions_fmt;
    }

    private function getGallerySkinArray()
    {
        $popup_skins = array("light_clean", "dark_clean", "pp_default", "light_rounded", "dark_rounded", "dark_square", "light_square", "facebook");
        $popup_skins_fmt = array();
        foreach ($popup_skins as $skin) {
            $popup_skins_fmt[] = array("id" => $skin, "name" => $skin);
        }

        return $popup_skins_fmt;
    }

    private function displayForm()
    {
        $default_lang = (int)Configuration::get('PS_LANG_DEFAULT');

        $fields_form = array(
            'form' => array(
                "legend" => array(
                    "title" => $this->l('Settings'),
                    "icon"  => "icon-cogs"
                ),
                'description' => $this->l("Review field notes below or visit this page for additional information: https://www.webrotate360.com/products/cms-and-e-commerce-plugins/plugin-for-prestashop.aspx?section=Installation"),
                "input" => array(
                    array(
                        "type"      => "text",
                        "label"     => $this->l("Placeholder (#id or .class)"),
                        "name"      => "wr360_placeholder",
                        "required"  => true,
                        "desc"      => $this->l("Class or id of an existing HTML element on a product page. This module will replace any content under this element for configured products. If 'In Popup' below is set to Yes, it will create a clickable 360 thumbnail instead of embedded 360 product viewer. Default value (.product-cover) with In Popup set to 'no' will make it integrate in to the product gallery in which case width and height properties below are ignored."),
                    ),
                    array(
                        "type"      => "text",
                        "label"     => $this->l("Width (px or %)"),
                        "name"      => "wr360_viewer_width",
                        "required"  => true,
                        "desc"      => $this->l("Viewer width in pixel or %. Popup mode requires pixel width (e.g 600px)."),
                    ),
                    array(
                        "type"      => "text",
                        "label"     => $this->l("Height (px)"),
                        "name"      => "wr360_viewer_height",
                        "required"  => true,
                        "desc"      => $this->l("Viewer height in pixel (e.g 500px). If Base Width is configured below, the height will scale responsively."),
                    ),
                    array(
                        "type"      => "text",
                        "label"     => $this->l("Base Width (px)"),
                        "name"      => "wr360_base_width",
                        "required"  => false,
                        "desc"      => $this->l("Original viewer width in pixel. If specified, this forces the viewer to scale its height relative to your original viewer width (Base Width). This setting only applies when viewer width is relative (%) which is not supported in the popup mode."),
                    ),
                    array(
                        "type"      => "text",
                        "label"     => $this->l("Minimum Height (px)"),
                        "name"      => "wr360_min_height",
                        "required"  => false,
                        "desc"      => $this->l("If Base Width is configured, this is a minimum viewer height in pixel (e.g 300px)."),
                    ),
                    array(
                        "type"      => "select",
                        "label"     => $this->l("Viewer Skin"),
                        "name"      => "wr360_skin",
                        "desc"      => $this->l("Selection of default viewer skins."),
                        "options"   => array(
                            "query" => $this->getViewerSkinArray(),
                            "id"    => "id",
                            "name"  => "name",
                        ),
                    ),
                    array(
                        "type"      => "select",
                        "label"     => $this->l("Position in product gallery"),
                        "name"      => "wr360_gallery_order",
                        "desc"      => $this->l("Select whether to show 360 thumbnail first or last in the gallery. Applicable when viewer is embedded via default placeholder (.product-cover)"),
                        "options"   => array(
                            "query" => $this->getGalleryOrder(),
                            "id"    => "id",
                            "name"  => "name",
                        ),
                    ),
                    array(
                        "type"      => "select",
                        "label"     => $this->l("In Popup"),
                        "name"      => "wr360_viewer_inpopup",
                        "desc"      => $this->l("In the popup mode, a small thumbnail graphic is inserted inside the placeholder which activates a popup with a product view on click. Thumbnail graphic is located under /modules/webrotate360 as 360thumb.svg."),
                        "options"   => array(
                            "query" => $this->getYesNoArray(),
                            "id"    => "id",
                            "name"  => "name",
                        ),
                    ),
                    array(
                        "type"      => "select",
                        "label"     => $this->l("Popup Skin"),
                        "name"      => "wr360_popup_skin",
                        "desc"      => $this->l("Skin of the popup 'lightbox' in the popup mode (In Popup is selected)."),
                        "options"   => array(
                            "query" => $this->getGallerySkinArray(),
                            "id"    => "id",
                            "name"  => "name",
                        ),
                    ),
                    array(
                        "type"      => "select",
                        "label"     => $this->l("Use Analytics (PRO)"),
                        "name"      => "wr360_use_analytics",
                        "desc"      => $this->l("If Google Analytics is integrated in your store, this enables tracking of the viewer analytics events under your Google Analytics Dashboard (PRO and Enterprise)."),
                        "options"   => array(
                            "query" => $this->getYesNoArray(),
                            "id"    => "id",
                            "name"  => "name",
                        ),
                    ),
                    array(
                        "type"      => "text",
                        "label"     => $this->l("API Callback"),
                        "name"      => "wr360_api_callback",
                        "required"  => false,
                        "desc"      => $this->l("To integrate with viewer API, enter the name of your JavaScript callback. The callback receives two parameters, e.g rotatorCallback(apiObj, isFullScreen). Only works when In Popup is not selected."),
                    ),
                    array(
                        "type"      => "text",
                        "label"     => $this->l("Master Config URL (PRO)"),
                        "name"      => "wr360_master_config",
                        "required"  => false,
                        "desc"      => $this->l("Master Config allows having a single (xml) configuration file for multiple products and only supply Root Path to the images folder of each product (under Catalog->Products->Product->WebRotate 360). Root Path can point to an external server, CDN, etc. To activate, enter a URL of your master config (xml) file on this server."),
                    ),
                    array(
                        "type"      => "text",
                        "label"     => $this->l("License Path"),
                        "name"      => "wr360_license",
                        "required"  => false,
                        "desc"      => $this->l("URL of license.lic on this server. The file is provided upon purchase. Use relative URL if your website doesn't always redirect to www (or no www).")
                    ),
                ),
                "submit" => array(
                    "title" => $this->l("Save"),
                    "class" => "button pull-right"
                )
            ),
        );

        $helper = new HelperForm();

        $helper->module                   = $this;
        $helper->name_controller          = $this->name;
        $helper->token                    = Tools::getAdminTokenLite('AdminModules');
        $helper->currentIndex             = AdminController::$currentIndex . '&configure=' . $this->name;
        $helper->default_form_language    = $default_lang;
        $helper->allow_employee_form_lang = $default_lang;
        $helper->title                    = $this->displayName;
        $helper->show_toolbar             = false;
        $helper->submit_action            = "submit" . $this->name;
        $helper->identifier               = $this->identifier;

        $helper->fields_value["wr360_placeholder"]    = Configuration::get("wr360_placeholder");
        $helper->fields_value["wr360_viewer_width" ]  = Configuration::get("wr360_viewer_width");
        $helper->fields_value["wr360_viewer_height"]  = Configuration::get("wr360_viewer_height");
        $helper->fields_value["wr360_base_width"]     = Configuration::get("wr360_base_width");
        $helper->fields_value["wr360_master_config"]  = Configuration::get("wr360_master_config");
        $helper->fields_value["wr360_license"]        = Configuration::get("wr360_license");
        $helper->fields_value["wr360_skin"]           = Configuration::get("wr360_skin");
        $helper->fields_value["wr360_popup_skin"]     = Configuration::get("wr360_popup_skin");
        $helper->fields_value["wr360_viewer_inpopup"] = Configuration::get("wr360_viewer_inpopup");
        $helper->fields_value["wr360_min_height"]     = Configuration::get("wr360_min_height");
        $helper->fields_value["wr360_use_analytics"]  = Configuration::get("wr360_use_analytics");
        $helper->fields_value["wr360_api_callback"]   = Configuration::get("wr360_api_callback");
        $helper->fields_value["wr360_gallery_order"]  = Configuration::get("wr360_gallery_order");

        return $helper->generateForm(array($fields_form));
    }
}
