<?php
/**
 * Module to show "add to cart" button in products list for Prestashop 1.7.x +
 * 
 * @author    Singleton software <info@singleton-software.com>
 * @copyright 2017 Singleton software
 * @license   http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
 */

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

class AddToCartInCatalog extends Module
{
	public function __construct()
	{
		$this->name = 'addtocartincatalog';
		$this->tab = 'front_office_features';
		$this->version = '1.4.0';
		$this->author = 'Singleton software';
		$this->module_key = 'c2c8b0d5a82c51036f4bb77ff133a6b5';
        $this->author_address = '0x82BBBf54B369bf4dB2704ed3b97c85294950231C';
		$this->need_instance = 0;
		$this->ps_versions_compliancy = array('min' => '1.7.0.0', 'max' => _PS_VERSION_ );
		$this->bootstrap = true;
		parent::__construct();
		$this->displayName = $this->l('Add to cart button in products list for Prestashop 1.7.x +');
		$this->description = $this->l('Module to show "add to cart" button in products list for Prestashop 1.7.x +');
		$this->confirmUninstall = $this->l('Are you sure you want to uninstall?');
		if (!Configuration::get($this->name))      
			$this->warning = $this->l('No name provided');
	}
	public function install()
	{
		$addToCardInCatalogData = $this->initAddToCardInCatalogConfigData();
		if (!parent::install() || !Configuration::updateGlobalValue($this->name, json_encode($addToCardInCatalogData)) || !$this->registerHook('displayHeader') || !$this->registerHook('displayProductPriceBlock'))
			return false;
		return true;
	}
	public function uninstall()
	{
		return (parent::uninstall() && Configuration::deleteByName($this->name) && $this->unregisterHook('displayHeader') && $this->unregisterHook('displayProductPriceBlock'));
	}
	public function getContent()
	{
		$settingsUpdated = '';
		if (Tools::isSubmit('submitAddToCardInCatalogData'))
		{
			$updateAddToCardInCatalogConfigData = array();
			$updateAddToCardInCatalogConfigData['show_in_category'] = Tools::getValue('show_in_category');
			$updateAddToCardInCatalogConfigData['show_in_popular'] = Tools::getValue('show_in_popular');
			$updateAddToCardInCatalogConfigData['show_in_search'] = Tools::getValue('show_in_search');
			$updateAddToCardInCatalogConfigData['show_in_related'] = Tools::getValue('show_in_related');
			$updateAddToCardInCatalogConfigData['show_quantity'] = Tools::getValue('show_quantity');
			$updateAddToCardInCatalogConfigData['progress_wheel'] = Tools::getValue('progress_wheel');
			$updateAddToCardInCatalogConfigData['button_type'] = Tools::getValue('button_type');
			$updateAddToCardInCatalogConfigData['button_display_type'] = Tools::getValue('button_display_type');
			$updateAddToCardInCatalogConfigData['image_position'] = Tools::getValue('image_position');
			$updateAddToCardInCatalogConfigData['background_color'] = Tools::getValue('background_color');
			$updateAddToCardInCatalogConfigData['background_color_hover'] = Tools::getValue('background_color_hover');
			$updateAddToCardInCatalogConfigData['text_color'] = Tools::getValue('text_color');
			$updateAddToCardInCatalogConfigData['border_radius'] = Tools::getValue('border_radius');
            $updateAddToCardInCatalogConfigData['thumbnail_parent_path'] = Tools::getValue('thumbnail_parent_path');
            $updateAddToCardInCatalogConfigData['thumbnail_container_path'] = Tools::getValue('thumbnail_container_path');
            $updateAddToCardInCatalogConfigData['append_to_path'] = Tools::getValue('append_to_path');
			foreach (Language::getLanguages(false) as $key => $value)
				$updateAddToCardInCatalogConfigData['button_text'][$value['id_lang']] = Tools::getValue('button_text_'.$value['id_lang']);
			Configuration::updateValue($this->name, json_encode($updateAddToCardInCatalogConfigData));
			$settingsUpdated .= $this->displayConfirmation($this->l('Settings updated'));
		}
		
		$this->smarty->assign(
			array(
				'moduleDir' => _MODULE_DIR_,
				'translate' => json_encode($this->getTranslates())
			)
		);
		return $settingsUpdated.$this->display(__FILE__,'BOconfig.tpl').$this->displayForm();
	}
	public function displayForm()
	{
		$default_lang = (int)Configuration::get('PS_LANG_DEFAULT');
		$helper = new Helper();
		$selectButtonType = array(
			array(
				'id_option' => '1',
				'name' => 'Only text'           
			),
			array(
				'id_option' => '2',
				'name' => 'Only image'
			),
			array(
				'id_option' => '3',
				'name' => 'Text and Image'
			)
		);
		$fields_form = array();
		$fields_form[0]['form'] = array(
			'legend' => array(
				'title' => $this->l('Settings'),
			),
			'input' => array(
				array(
					'type'		=>'switch',
					'label'     => $this->l('Show button in products categories:'),
					'desc'      => $this->l('You can display "add to cart" button in product categories.'),
					'name'      => 'show_in_category',
					'required'  => false,
					'class'     => 'showInCategory',
					'is_bool'   => true,
					'values'    => array(
						array(
							'id'    => 'show_in_category_on',
							'value' => 1,
							'label' => $this->l('No')
						),
						array(
							'id'    => 'show_in_category_off',
							'value' => 0,
							'label' => $this->l('Yes')
						)
					)
				),
				array(
					'type'		=>'switch',
					'label'     => $this->l('Show button in search results:'),
					'desc'      => $this->l('You can display "add to cart" button in product list of search result.'),
					'name'      => 'show_in_search',
					'required'  => false,
					'class'     => 'showInSearch',
					'is_bool'   => true,
					'values'    => array(
						array(
							'id'    => 'show_in_search_on',
							'value' => 1,
							'label' => $this->l('No')
						),
						array(
							'id'    => 'show_in_search_off',
							'value' => 0,
							'label' => $this->l('Yes')
						)
					)
				),
				array(
					'type'		=>'switch',
					'label'     => $this->l('Show button in popular products:'),
					'desc'      => $this->l('You can display "add to cart" button in popular products section on home page.'),
					'name'      => 'show_in_popular',
					'required'  => false,
					'class'     => 'showInPopular',
					'is_bool'   => true,
					'values'    => array(
						array(
							'id'    => 'show_in_popular_on',
							'value' => 1,
							'label' => $this->l('No')
						),
						array(
							'id'    => 'show_in_popular_off',
							'value' => 0,
							'label' => $this->l('Yes')
						)
					)
				),
				array(
					'type'		=>'switch',
					'label'     => $this->l('Show button in related products list:'),
					'desc'      => $this->l('You can display "add to cart" button in related products list in product detail.'),
					'name'      => 'show_in_related',
					'required'  => false,
					'class'     => 'showInRelated',
					'is_bool'   => true,
					'values'    => array(
						array(
							'id'    => 'show_in_related_on',
							'value' => 1,
							'label' => $this->l('No')
						),
						array(
							'id'    => 'show_in_related_off',
							'value' => 0,
							'label' => $this->l('Yes')
						)
					)
				),
				array(
					'type'		=>'switch',
					'label'     => $this->l('Allow to choose quantity of products:'),
					'desc'      => $this->l('You can display quantity to choose for each product, which will be displayed on the left side of "add to cart" button.'),
					'name'      => 'show_quantity',
					'required'  => false,
					'class'     => 'showQuantity',
					'is_bool'   => true,
					'values'    => array(
						array(
							'id'    => 'show_quantity_on',
							'value' => 1,
							'label' => $this->l('Yes')
						),
						array(
							'id'    => 'show_quantity_off',
							'value' => 0,
							'label' => $this->l('No')
						)
					)
				),
				array(
					'type'		=>'switch',
					'label'     => $this->l('Progress wheel while product is adding to cart:'),
					'desc'      => $this->l('You can display progress wheel while product is adding to cart. Progress wheel will be displayed at the top of "add to cart" button. This option will be apply also to "add to cart" button in product detail.'),
					'name'      => 'progress_wheel',
					'required'  => false,
					'class'     => 'progressWheel',
					'is_bool'   => true,
					'values'    => array(
						array(
							'id'    => 'progress_wheel_on',
							'value' => 1,
							'label' => $this->l('Yes')
						),
						array(
							'id'    => 'progress_wheel_off',
							'value' => 0,
							'label' => $this->l('No')
						)
					)
				),
				array(
					'type'		=> 'radio',
					'label'     => $this->l('Button style:'),
					'desc'      => $this->l('You can choose if "add to cart" button in products list will be look like "add to cart" button in product detail, or you can customize your own design of this button.'),
					'name'      => 'button_display_type',
					'required'  => false,
					'class'     => 'buttonDisplayType',
					'is_bool'   => false,
					'values'    => array(
						array(
							'id'    => 'button_display_type_0',
							'value' => 0,
							'label' => $this->l('The same style like in product detail')
						),
						array(
							'id'    => 'button_display_type_1',
							'value' => 1,
							'label' => $this->l('Custom button style')
						)
					)
				),
				array(
					'type'		=> 'radio',
					'label'     => $this->l('Button text and icon:'),
					'desc'      => $this->l('You can choose if your customized "add to cart" button will contain only text, only cart icon, or both.'),
					'name'      => 'button_type',
					'required'  => false,
					'class'     => 'buttonType',
					'is_bool'   => false,
					'values'    => array(
						array(
							'id'    => 'button_type_0',
							'value' => 0,   
							'label' => $this->l('Only text')
						),
						array(
							'id'    => 'button_type_1',
							'value' => 1,   
							'label' => $this->l('Only cart')
						),
						array(
							'id'    => 'button_type_2',
							'value' => 2,
							'label' => $this->l('Text and cart icon')
						)
					)
				),
				array(
					'type'     => 'text',
					'label'    => $this->l('Text:'),
					'name'     => 'button_text',
					'class'    => 'buttonText',
					'required' => false,
					'lang'		=> true,
					'desc'     => $this->l('You can set you own text in each language which will be displayed in "add to cart" button.')
				),
				array(
					'type'		=> 'radio',
					'label'     => $this->l('Cart icon position:'),
					'desc'      => $this->l('You can choose if cart icon will be displayed in left side, or right side of text in "add to cart" button.'),
					'name'      => 'image_position',
					'required'  => false,
					'class'     => 'imagePosition',
					'is_bool'   => false,
					'values'    => array(
						array(
							'id'    => 'image_position_0',
							'value' => 0,
							'label' => $this->l('On the left side of the text')
						),
						array(
							'id'    => 'image_position_1',
							'value' => 1,
							'label' => $this->l('On the right side of the text')
						)
					)
				),
				array(
					'type'     => 'color',
					'label'    => $this->l('Text and cart icon color:'),
					'name'     => 'text_color',
					'class'    => 'textColor',
					'required' => false,
					'desc'     => $this->l('Text and cart icon color in "add to cart" button.')
				),
				array(
					'type'     => 'color',
					'label'    => $this->l('Background color:'),
					'name'     => 'background_color',
					'class'    => 'backgroundColor',
					'required' => false,
					'desc'     => $this->l('Background color of "add to cart" button.')
				),
				array(
					'type'     => 'color',
					'label'    => $this->l('Background color on mouse over:'),
					'name'     => 'background_color_hover',
					'class'    => 'backgroundColorHover',
					'required' => false,
					'desc'     => $this->l('Background color of "add to cart" button if mouse cursor slide over this button.')
				),
				array(
					'type'		=>'switch',
					'label'     => $this->l('Show border radius on button:'),
					'desc'      => $this->l('You can choose if "add to cart" button will have rounded corners.'),
					'name'      => 'border_radius',
					'required'  => false,
					'class'     => 'borderRadius',
					'is_bool'   => true,
					'values'    => array(
						array(
							'id'    => 'border_radius_on',
							'value' => 1,
							'label' => $this->l('No')
						),
						array(
							'id'    => 'border_radius_off',
							'value' => 0,
							'label' => $this->l('Yes')
						)
					)
				),
                array(
                    'type'     => 'hidden',
                    'label'    => 'thumbnailParentPath',
                    'name'     => 'thumbnail_parent_path',
                    'class'    => 'thumbnailParentPath',
                    'required' => false,
                    'lang'		=> false
                ),
                array(
                    'type'     => 'hidden',
                    'label'    => 'thumbnailContainerPath',
                    'name'     => 'thumbnail_container_path',
                    'class'    => 'thumbnailContainerPath',
                    'required' => false,
                    'lang'		=> false
                ),
                array(
                    'type'     => 'hidden',
                    'label'    => 'appendToPath',
                    'name'     => 'append_to_path',
                    'class'    => 'appendToPath',
                    'required' => false,
                    'lang'		=> false
                ),
			),
			'submit' => array(
				'title' => $this->l('Save'),
				'name' => 'submitAddToCardInCatalogData',
			)
		);
		$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->toolbar_scroll = false;
		$helper->submit_action = 'submit'.$this->name;
		$helper->tpl_vars = array(
			'fields_value' => json_decode(Configuration::get($this->name), true),
			'languages' => $this->context->controller->getLanguages(),
			'id_language' => $this->context->language->id
		);
		return $helper->generateForm($fields_form);
	}
	public function initAddToCardInCatalogConfigData()
	{
		$addToCardInCatalogConfigData = array();
		$addToCardInCatalogConfigData['show_in_category'] = '0';
		$addToCardInCatalogConfigData['show_in_popular'] = '0';
		$addToCardInCatalogConfigData['show_in_search'] = '0';
		$addToCardInCatalogConfigData['show_in_related'] = '0';
		$addToCardInCatalogConfigData['show_quantity'] = '0';
		$addToCardInCatalogConfigData['progress_wheel'] = '0';
		$addToCardInCatalogConfigData['button_display_type'] = '0';
		$addToCardInCatalogConfigData['button_type'] = '0'; //iba text, iba obrazok, aj text aj obrazok
		$addToCardInCatalogConfigData['image_position'] = '0';
		foreach (Language::getLanguages(false) as $key => $value)
			$addToCardInCatalogConfigData['button_text'][$value['id_lang']] = $this->l('ADD TO CART');
		$addToCardInCatalogConfigData['background_color'] = '#2fb5d2';
		$addToCardInCatalogConfigData['background_color_hover'] = '#2592a9';
		$addToCardInCatalogConfigData['text_color'] = '#ffffff';
		$addToCardInCatalogConfigData['border_radius'] = '0';
        $addToCardInCatalogConfigData['thumbnail_parent_path'] = 'article';
        $addToCardInCatalogConfigData['thumbnail_container_path'] = '.thumbnail-container';
        $addToCardInCatalogConfigData['append_to_path'] = '.product-price-and-shipping';
		return $addToCardInCatalogConfigData;
	}
	
	public function hookDisplayHeader($params)
	{
		$this->context->controller->registerStylesheet('modules-addtocardincatalog-style', 'modules/'.$this->name.'/views/css/style.css', array('media' => 'all', 'priority' => 150));
		$this->context->controller->registerJavascript('modules-addtocardincatalog-global', 'modules/'.$this->name.'/views/js/global.js', array('position' => 'bottom', 'priority' => 150));
		$addToCartInCatalogConfig = json_decode(Configuration::get($this->name), true);
		$this->smarty->assign(
			array(
				'addToCartInCatalogConfigData' => $addToCartInCatalogConfig,
				'addToCartInCatalogConfigDataJson' => Configuration::get($this->name),
				'addToCartInCatalogButtonText' => $addToCartInCatalogConfig['button_text'][$this->context->language->id],
                'greaterThan1750' => version_compare(_PS_VERSION_, '1.7.5', '>='),
			)
		);
		return $this->display(__FILE__, 'views/templates/hook/global.tpl');
	}
	
	public function hookDisplayProductPriceBlock($params) {
		if ($params['type'] == 'before_price') {
			$addProdDisplay = Configuration::get('PS_ATTRIBUTE_CATEGORY_DISPLAY');
			$isCatalogMode = Configuration::isCatalogMode();
			$allowToShowButton = false;
			if ($params['product']['available_for_order'] && $params['product']['customizable'] != 2 && !$isCatalogMode && (!Tools::getIsset($params['product']['customization_required']) || !$params['product']['customization_required']) && ($params['product']['allow_oosp'] || $params['product']['quantity'] > 0)) {
				$allowToShowButton = true;
			}
			$this->smarty->assign(
				array(
					'allowToShowButton' => $allowToShowButton,
                    'maxinmalQuantity' => $params['product']['quantity'],
                    'productAttributeMinimalQuantity' => $params['product']['product_attribute_minimal_quantity'],
                    'quantityWanted' => $this->getRequiredQuantity($params['product']),
                    'minimalQuantity' => $this->getProductMinimalQuantity($params['product'])
				)
			);
			return $this->display(__FILE__, 'views/templates/hook/productPriceBlock.tpl');
		}
	}

    private function getRequiredQuantity($product)
    {
        $requiredQuantity = (int) Tools::getValue('quantity_wanted', $this->getProductMinimalQuantity($product));
        if ($requiredQuantity < $product['minimal_quantity']) {
            $requiredQuantity = $product['minimal_quantity'];
        }
        return $requiredQuantity;
    }

    private function getProductMinimalQuantity($product)
    {
        $minimal_quantity = 1;
        if ($product['id_product_attribute']) {
            $combination = $this->findProductCombinationById($product['id_product'], $product['id_product_attribute']);
            if ($combination['minimal_quantity']) {
                $minimal_quantity = $combination['minimal_quantity'];
            }
        } else {
            $minimal_quantity = $product['minimal_quantity'];
        }
        return $minimal_quantity;
    }

    private function findProductCombinationById($idProduct, $combinationId)
    {
        $foundCombination = null;
        $product = new Product($idProduct);
        $combinations = $product->getAttributesGroups($this->context->language->id);
        foreach ($combinations as $combination) {
            if ((int) ($combination['id_product_attribute']) === $combinationId) {
                $foundCombination = $combination;
                break;
            }
        }
        return $foundCombination;
    }
	
	private function getTranslates()
	{
		return array(
			'AddToCartButtonLivePreview' => $this->l('Add to cart custom button Live preview'),
			'emptyText' => $this->l('Button text have to be filled (in each language)')
		);
	}
}