<?php
class ModelExtensionAnalyticsScriptManager extends Model
{
    public function getScripts()
    {
        $header_only = (int)$this->config->get('analytics_script_manager_header_ajax');
        if ($header_only) {
            if (array_key_exists('scriptmanager', $this->session->data)) {
                $manager_scripts = $this->session->data['scriptmanager'];
            } else {//is other page
                $this->setGoogleScript(); //set base script
                $this->setFacebookScript(); //set base script
                $this->setDynamicScript(); //set base script
                $manager_scripts = $this->session->data['scriptmanager'];
            }
            $scripts = array();
            if (array_key_exists('google', $manager_scripts)) {
                $scripts[]= $this->getOptimizeAntiFlickerScript().$this->getGoogleLink().$this->setScriptTag($this->getGoogleHeader().$manager_scripts['google'], 1, 1);
            }
            if (array_key_exists('facebook', $manager_scripts)) {
                $scripts[]= $this->setScriptTag($this->getFacebookHeader().$manager_scripts['facebook'], 1, 1);
            }
            if (array_key_exists('custom', $manager_scripts)) {
                $scripts[]= $this->getCustomHeader().$this->setScriptTag($manager_scripts['custom'], 1, 0);
            }
            unset($this->session->data['scriptmanager']);//clear data
            return implode($scripts);
        } else {
            return $this->getHeaderScripts();
        }
        return "";
    }

    public function getHeaderScripts()
    {
        $script = $this->getOptimizeAntiFlickerScript().$this->getGoogleLink().$this->setScriptTag($this->getGoogleHeader(), 1, 1);
        $script.= $this->setScriptTag($this->getFacebookHeader(), 1, 1);
        $script.= $this->getCustomHeader();//script tag already set
        return $script;
    }

    public function setScripts($page_type = '', $products = array(), $order_id = '')
    {
        //$this->tax->setShippingAddress($this->config->get('config_country_id'), $this->config->get('config_zone_id'));//set taxes to store address
        $this->setProducts($page_type, $products, $order_id);//process product list
        $this->setGoogleScript($page_type, $products, $order_id);//create google scripts
        $this->setFacebookScript($page_type, $products, $order_id);
        $this->setDynamicScript($page_type, $products, $order_id);
    }

    public function setProducts($page_type, $products, $order_id)
    {
        $google_merchant_id1_list = array();
        $google_adwords_id1_list = array();
        $google_adwords_id2_list = array();
        $facebook_pid_list = array();
        $analytics_products = array();
        $merchant_products = array();
        //$google_product_ids = array();
        $ecommerce_products = array();
        $facebook_products = array();
        $this->total_value = 0;
        $this->total_value_tax = 0;
        $this->total_full_value = 0;
        $this->total_full_value_tax = 0;
        $ecommerce = (int)$this->config->get('analytics_script_manager_use_ecommerce');
        $facebook_id_type = ($this->config->get('analytics_script_manager_facebook_pid') == 'copy' ? $this->config->get('feed_facebook_catalog_pid1') : $this->config->get('analytics_script_manager_facebook_pid'));
        $google_option_ids = ($this->config->get('analytics_script_manager_google_option_ids') == 'copy' ? $this->config->get('feed_google_merchant_center_option_ids') : $this->config->get('analytics_script_manager_google_option_ids'));
        $facebook_option_ids = ($this->config->get('analytics_script_manager_facebook_option_ids') == 'copy' ? $this->config->get('feed_facebook_catalog_option_ids') : $this->config->get('analytics_script_manager_facebook_option_ids'));
        $google_options = $this->getSettingOptionIDs('analytics_script_manager_google_options', 'feed_google_merchant_center_');//script setting name, feed prefix setting name
        $facebook_options = $this->getSettingOptionIDs('analytics_script_manager_facebook_options', 'feed_facebook_catalog_');
        $coupon_info=0;
        $sub_total=0;
        $currency = $this->config->get('analytics_script_manager_facebook_currency');
        if ($currency === null) {
            $currency = $this->config->get('config_currency');
        } elseif ($currency === 'customer') {
            $currency = $this->session->data['currency'];
        } else {
            $currency = substr($currency, -3, 3);
        }
        /*$product_limit=count($products);
        if ($page_type == "category" || $page_type == "search") {//limit the number of products
            $product_limit = 10;
        }*/
        if ($page_type == 'purchase') {//total
            $this->load->model('extension/total/coupon');
            if (isset($this->session->data['coupon'])) {
                $sub_total = $this->getOrderSubTotal($order_id);
                $coupon_info = $this->model_extension_total_coupon->getCoupon($this->session->data['coupon']);
            }
        }
        foreach($products as $index => $product) {
            /*if ($product_limit <= $index) {
                break;
            }*/
            $discount = $this->getProductDiscount($products, $index, $sub_total, $coupon_info);
            $this->setGoogleIDs($google_merchant_id1, $google_adwords_id1, $google_adwords_id2, $product);
            $g_options = $this->getOptionsProduct($product, $google_options);
            $f_options = $this->getOptionsProduct($product, $facebook_options);
            $google_merchant_id1_list[] = $google_merchant_id1.$this->getOptionID($google_option_ids, $g_options);
            $google_adwords_id1_list[] = $google_adwords_id1;
            if ($google_adwords_id2 != '') {
                $google_adwords_id2_list[] = $google_adwords_id2;
            }
            $price = $this->getPrice($product)-$discount;
            $analytics_products[]=$this->getAnalyticsProduct($google_adwords_id1, $google_adwords_id2);
            $merchant_products[]=$this->getMerchantProduct($google_merchant_id1.$this->getOptionID($google_option_ids, $g_options));
            //$google_product_ids[]=$this->fixString($google_merchant_id1.$this->getOptionID($google_option_ids, $g_options));
            if ($ecommerce) {
                $position = "";
                if ($page_type == "category" || $page_type == "search") {
                    $position = $index+1;
                }
                $ecommerce_products[]= $this->getEcommerceProduct($google_merchant_id1, $product, $currency, $position);
            }
            $facebook_pid = "";
            if ($facebook_id_type=='model') {
                $facebook_pid = $product['model'];
            } else {
                $facebook_pid = $product['product_id'];
            }
            $facebook_pid = $facebook_pid.$this->getOptionID($facebook_option_ids, $f_options);
            $facebook_pid_list[] = $facebook_pid;
            $facebook_products[] = $this->getFacebookProduct($facebook_pid, $product, $currency);
            $this->total_value += $price*$product['quantity'];
            $this->total_value_tax += $this->tax->calculate($price, $product['tax_class_id'], 1)*$product['quantity'];
            $price_full = $product['price'];
            $this->total_full_value += $price_full*$product['quantity'];
            $this->total_full_value_tax += $this->tax->calculate($price_full, $product['tax_class_id'], 1)*$product['quantity'];
        }
        if ($this->total_value == 0) {
            $this->total_value = "";
        }
        if ($this->total_value_tax == 0) {
            $this->total_value_tax = "";
        }
        if ($this->total_full_value == 0) {
            $this->total_full_value = "";
        }
        if ($this->total_full_value_tax == 0) {
            $this->total_full_value_tax = "";
        }
        $this->google_merchant_id1_list = $google_merchant_id1_list;
        $this->google_adwords_id1_list = $google_adwords_id1_list;
        $this->google_adwords_id2_list = $google_adwords_id2_list;
        $this->facebook_pid_list = $facebook_pid_list;
        $this->analytics_products = $analytics_products;
        $this->merchant_products = $merchant_products;
        //$this->google_product_ids = $google_product_ids;
        $this->ecommerce_products = $ecommerce_products;
        $this->facebook_products = $facebook_products;
    }

    protected function getMerchantProduct($google_merchant_id1)
    {
        return "'id': '".$this->fixString($google_merchant_id1)."','google_business_vertical': 'retail'";
    }

    protected function getAnalyticsProduct($google_adwords_id1, $google_adwords_id2)
    {
        return "'id': '".$this->fixString($google_adwords_id1)."','location_id': '".$this->fixString($google_adwords_id2)."','google_business_vertical': 'custom'";
    }

    protected function getEcommerceProduct($google_merchant_id1, $product, $currency, $position = "")
    {
        $variants = array();
        if (isset($product['option']) && is_array($product['option'])) {
            foreach ($product['option'] as $option) {
                $variants[]=$option['value'];
            }
        }
        return "'id': '".$google_merchant_id1."', 'name': '".$this->fixString($product['name']).
(count($variants) ? "', 'variant': '".$this->fixString(implode(',',$variants)) : "").
"', 'brand': '".$this->fixString($product['manufacturer']).
((int)$product['quantity'] ? "', 'quantity': '".$product['quantity'] : "").
($product['category'][0] != "" ? "', 'list': '".$this->fixString($product['category'][count($product['category'])-1]) : "").
($position != "" ? "', 'list_position': '".$position : "").
($product['category'][0] != "" ? "', 'category': '".$this->fixString(implode("/", $product['category'])) : "").
"', 'price': ".$this->currency->format($this->getPrice($product), $currency,'',false);
    }

    protected function getFacebookProduct($facebook_pid, $product, $currency)
    {
        return "'id': '".$this->fixString($facebook_pid)."', 'quantity': ".$product['quantity'].", 'item_price': ".$this->currency->format($this->tax->calculate($this->getPrice($product), $product['tax_class_id'], $this->config->get('analytics_script_manager_facebook_tax')), $currency, '', false);
    }

    public function getGoogleLink()
    {
        $google_id = '';
        $analytics_id = $this->config->get('analytics_script_manager_analytics_id');
        $adwords_id = $this->config->get('analytics_script_manager_adwords_id');
        if ($analytics_id != '') {
            $google_id = $analytics_id;
        } elseif ($adwords_id != '') {
            $google_id = $adwords_id;
        } else {
            return '';//no adwords or analytics
        }
        return '<script async src="https://www.googletagmanager.com/gtag/js?id='.$google_id.'"></script>';
    }

    public function getOptimizeAntiFlickerScript()
    {
        $analytics_id = $this->config->get('analytics_script_manager_analytics_id');
        $optimize_id = $this->config->get('analytics_script_manager_optimize_id');
        $optimize_timeout = (int)$this->config->get('analytics_script_manager_optimize_timeout');
        //Google Optmize Page hide snippet
        if ($optimize_timeout > 0 && $optimize_id !== "" && $analytics_id !== "") {
            return "<style>.async-hide { opacity: 0 !important} </style>
<script>if (typeof doNotTrackMe !== \"function\" || !doNotTrackMe()) {
(function(a,s,y,n,c,h,i,d,e){s.className+=' '+y;h.start=1*new Date;
h.end=i=function(){s.className=s.className.replace(RegExp(' ?'+y),'')};
(a[n]=a[n]||[]).hide=h;setTimeout(function(){i();h.end=null},c);h.timeout=c;
})(window,document.documentElement,'async-hide','dataLayer',".$optimize_timeout.",
{'".$optimize_id."':true});}</script>";
        }
        return "";
    }

    public function getGoogleHeader()
    {
        //base
        $script = "
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());";
        return $script;
    }

    public function setGoogleScript($page_type = '', $products = array(), $order_id = '')
    {
        if ((int)$this->config->get('analytics_script_manager_status') != 1) {
            return;
        }
        if (empty($products)) {
            $this->google_merchant_id1_list = array();
            $this->google_adwords_id1_list = array();
            $this->google_adwords_id2_list = array();
            $this->analytics_products = array();
            $this->merchant_products = array();
            //$this->google_product_ids = array();
            $this->ecommerce_products = array();
        }
        //get settings
        $script = '';
        $search_string = '';
        $analytics_id = $this->config->get('analytics_script_manager_analytics_id');
        $adwords_id = $this->config->get('analytics_script_manager_adwords_id');
        $conversion_label = $this->config->get('analytics_script_manager_conversion_label');
        $optimize_id = $this->config->get('analytics_script_manager_optimize_id');
        $anonymize_ip = (int)$this->config->get('analytics_script_manager_anonymize_ip');
        $via_analytics = (int)$this->config->get('analytics_script_manager_use_analytics');
        $via_merchant = (int)$this->config->get('analytics_script_manager_use_merchant');
        $use_user_id = (int)$this->config->get('analytics_script_manager_google_user_id');
        $ecommerce = (int)$this->config->get('analytics_script_manager_use_ecommerce');
        $google_tax = (int)$this->config->get('analytics_script_manager_google_tax');
        $use_shipping = (int)$this->config->get('analytics_script_manager_google_shipping');
        $is_legacy = (int)$this->config->get('analytics_script_manager_use_google_legacy');
        $currency = $this->config->get('analytics_script_manager_google_currency');
        if ($analytics_id === '' && $adwords_id === '') {
            return;
        }
        if ($currency === null) {
            $currency = $this->config->get('config_currency');
        } elseif ($currency === 'customer') {
            $currency = $this->session->data['currency'];
        }
        if ($adwords_id != "" && substr($adwords_id,0,1) !== 'A') {
            $adwords_id = 'AW-'.$adwords_id;
        }
        //set event names
        $page_type_analytics = "other";
        $page_type_ecommerce = "";
        $page_type_adwords = "page_view";
        $page_type_ecomm_legacy = "other";
        if ($page_type == 'product') {
            $page_type_analytics = "offerdetail";
            $page_type_ecommerce = "view_item";
            $page_type_adwords = "view_item";
            $page_type_ecomm_legacy = "product";
        } elseif ($page_type == 'category') {
            $page_type_analytics = "searchresults";
            $page_type_ecommerce = "view_item_list";
            $page_type_adwords = "view_item_list";
            $page_type_ecomm_legacy = "category";
        } elseif ($page_type == 'search') {
            $page_type_analytics = "searchresults";
            $page_type_ecommerce = "view_search_results";//view_item_list
            $page_type_adwords = "view_search_results";
            $page_type_ecomm_legacy = "searchresults";
            $search_string = $this->getSearch();
        } elseif ($page_type == 'cart') {
            $page_type_analytics = "conversionintent";
            $page_type_ecommerce = "begin_checkout";
            $page_type_adwords = "page_view";
            $page_type_ecomm_legacy = "cart";
        } elseif ($page_type == 'checkout') {
            $page_type_analytics = "conversionintent";
            $page_type_ecommerce = "checkout_progress";
            $page_type_adwords = "page_view";
            $page_type_ecomm_legacy = "cart";
        } elseif ($page_type == 'purchase') {
            $page_type_analytics = "conversion";
            $page_type_ecommerce = "purchase";
            $page_type_adwords = "purchase";
            $page_type_ecomm_legacy = "purchase";
        } elseif ($page_type == 'home') {
            $page_type_analytics = "home";
            $page_type_ecommerce = "";//not used
            $page_type_adwords = "page_view";
            $page_type_ecomm_legacy = "home";
        } elseif ($page_type == 'login') {
            $page_type_analytics = "other";
            $page_type_ecommerce = "";//not used
            $page_type_adwords = "page_view";
            $page_type_ecomm_legacy = "other";
        } elseif ($page_type == 'registration') {
            $page_type_analytics = "other";
            $page_type_ecommerce = "";//not used
            $page_type_adwords = "page_view";
            $page_type_ecomm_legacy = "other";
        }
        $page_name = $this->fixString($this->document->getTitle());
        $page_name = ($page_name == "" ? ucfirst($page_type) : $page_name);
        //set total prices
        if ($google_tax) {
            $total_value_google = $this->currency->format($this->total_value_tax, $currency,'',false);
        } else {
            $total_value_google = $this->currency->format($this->total_value, $currency,'',false);
        }
        $shipping_price = 0;
        $shipping_tax = 0;
        if ($page_type == 'purchase') {
            $this->load->model('checkout/order');
            $free_shipping = false;
            if (isset($this->session->data['coupon'])) {
                $this->load->model('extension/total/coupon');
                $coupon_info = $this->model_extension_total_coupon->getCoupon($this->session->data['coupon']);
                $free_shipping = $this->getShippingDiscount($coupon_info);
            }
            if (!$free_shipping) {
                $shipping_price = $this->model_checkout_order->getOrderShipping($order_id);
                if (isset($this->session->data['shipping_method'])) {//need tax_class_id to calculate tax
                    $shipping_tax = $this->tax->calculate($shipping_price, $this->session->data['shipping_method']['tax_class_id'], 1)-$shipping_price;
                }
                $shipping_price = $this->currency->format($shipping_price, $currency,'',false);
                $shipping_tax = $this->currency->format($shipping_tax, $currency,'',false);
            }
        }
        $script = "";
    //analytics script
        if ($analytics_id != "") {//scripts that require analytics
            $script .= "
gtag('config', '".$analytics_id."'";
            if ($via_analytics || $optimize_id != "" || $anonymize_ip) {
                $itemid = $this->config->get('analytics_script_manager_dimension_itemid');
                $itemid2 = $this->config->get('analytics_script_manager_dimension_itemid2');//second id, skip if not used
                $pagetype = $this->config->get('analytics_script_manager_dimension_pagetype');
                $totalvalue = $this->config->get('analytics_script_manager_dimension_totalvalue');
                $script .= ",
{".($optimize_id != "" ? "'optimize_id': '".$optimize_id."',
" : "").($anonymize_ip ? "'anonymize_ip': true,
" : "").(($via_analytics && $itemid!=="") ? "'custom_map': {
'dimension".(int)$itemid."': 'dynx_itemid',
".($itemid2 !== "" ? "'dimension".(int)$itemid2."': 'dynx_itemid2',
" : "").($pagetype !== "" ? "'dimension".(int)$pagetype."': 'dynx_pagetype',
" : "").($totalvalue !== "" ? "'dimension".(int)$totalvalue."': 'dynx_totalvalue'
" : "")."
}" : "")."});";
            } else {//close config
                $script .= ");";
            }

            //user id for analytics
            if ($use_user_id && $this->customer->getId() != "") {
                $script .= "
gtag('set', {'user_id': '".$this->customer->getId()."'});";
            }

            //remarketing via analytics
            if ($via_analytics) {
                $script .="
gtag('event', 'remarketing', {
'send_to': '".$analytics_id."',
'non_interaction': true,
'dynx_itemid': ".((count($this->google_adwords_id1_list)>=1 && $page_type != 'category' && $page_type != 'search') ? "['".implode("','", $this->google_adwords_id1_list)."']" : "''").",
'dynx_itemid2': ".((count($this->google_adwords_id2_list)>=1 && $page_type != 'category' && $page_type != 'search') ? "['".implode("','", $this->google_adwords_id2_list)."']" : "''").",
'dynx_pagetype': '".$page_type_analytics."',
'dynx_totalvalue': '".($total_value_google > 0 && $page_type != 'category' && $page_type != 'search' ? $total_value_google : "")."'
});";
            }

            //ecommerce with success page check
            if ($ecommerce && $page_type_ecommerce != "") {
                $script .= "
gtag('event', '".$page_type_ecommerce."', {".
($page_type == 'purchase' ?  "
'affiliation': '".$_SERVER['HTTP_HOST']."',
'value': '".$this->currency->format((float)$this->total_value, $currency,'',false)."',
'tax': '".($this->currency->format((float)$this->total_value_tax-(float)$this->total_value, $currency,'',false)+(float)$shipping_tax)."',
'shipping': '".$shipping_price."',
'currency': '".$currency."',
'transaction_id': '".$order_id."'," : "")."
'send_to': '".$analytics_id."',
'non_interaction': true,".($search_string === "" ? "" : "
'search_term': '".$search_string."',")."
'event_label': '".$page_name."',
'items': [{".implode('},{', $this->ecommerce_products)."}]
});";
            }
        }

        //adwords remarketing
        if ($adwords_id != "" && ($via_merchant || $via_analytics)) {
            $script .= "
gtag('config', '".$adwords_id."');".
            (!$is_legacy && (count($this->merchant_products) || count($this->analytics_products)) ? "
gtag('event', '".$page_type_adwords."', {
'send_to': '".$adwords_id."',
'non_interaction': true,
'value': '".($total_value_google == 0 ? "" : $total_value_google)."',
'items': [".($via_analytics == 1 ? "{".implode('},{', $this->analytics_products)."}": "").
($via_analytics == 1 && $via_merchant == 1 ? ",
" : "").
($via_merchant == 1 ? "{".implode('},{', $this->merchant_products)."}": "")."]
});" : "")

.($is_legacy ? "
gtag('event', 'page_view', {
'send_to': '".$adwords_id."',
'non_interaction': true,
".($via_analytics == 1 ? "'dynx_itemid': ".((count($this->google_adwords_id1_list)>=1 && $page_type != 'category' && $page_type != 'search') ? "['".implode("','", $this->google_adwords_id1_list)."']" : "''").",
'dynx_itemid2': ".((count($this->google_adwords_id2_list)>=1 && $page_type != 'category' && $page_type != 'search') ? "['".implode("','", $this->google_adwords_id2_list)."']" : "''").",
'dynx_pagetype': '".$page_type_analytics."',
'dynx_totalvalue': '".($total_value_google > 0 && $page_type != 'category' && $page_type != 'search' ? $total_value_google : "")."'" : "").
($via_analytics == 1 && $via_merchant == 1 ? ",
" : "").
($via_merchant == 1 ? "'ecomm_prodid': ".((count($this->google_merchant_id1_list)>=1 && $page_type != 'category' && $page_type != 'search') ? "['".implode("','", $this->google_merchant_id1_list)."']" : "''").",
'ecomm_pagetype': '".$page_type_ecomm_legacy."',
'ecomm_category': '".(count($products)>0 ? $this->fixString(implode(' > ', $products[0]['category'])) : "")."',
'ecomm_totalvalue': '".($total_value_google > 0 && $page_type != 'category' && $page_type != 'search' ? $total_value_google : "")."'" : "")."
});" : "");

            //google coversion
            if ($conversion_label != "" && $page_type == 'purchase') {
                $shipping = 0;
                if ($use_shipping) {
                    if ($google_tax) {
                        $shipping = $shipping_price + $shipping_tax;
                    } else {
                        $shipping = $shipping_price;
                    }
                }
                $script .="
gtag('event', 'conversion', {
'send_to': '".$adwords_id."/".$conversion_label."',
'value': ".($total_value_google + $shipping).",
'currency': '".$currency."',
'transaction_id': '".$order_id."'
});";
            }
        }
        $this->session->data['scriptmanager']['google'] = html_entity_decode($script, ENT_QUOTES, 'UTF-8');
    }

    public function getFacebookHeader()
    {
        $facebook_id = $this->config->get('analytics_script_manager_facebook_id');
        if ((int)$this->config->get('analytics_script_manager_status') != 1 || $facebook_id == '') {
            return '';
        }
        //set Advanced Matching
        $advanced_matching = (int)$this->config->get('analytics_script_manager_facebook_advanced_matching');
        $customer_email='';
        $customer_firstname='';
        $customer_lastname='';
        $customer_phone='';
        $advanced_matching_data = array();
        if ($advanced_matching) {
            if ($this->customer->isLogged()){
                $customer_email = mb_strtolower($this->customer->getEmail());
                $customer_firstname = mb_strtolower($this->customer->getFirstName());
                $customer_lastname = mb_strtolower($this->customer->getLastName());
                $customer_phone = mb_strtolower(preg_replace('/\s/', '', $this->customer->getTelephone()));
            } elseif (isset($this->session->data['guest'])){
                if (isset($this->session->data['guest']['email']) && $this->session->data['guest']['email'] != "") {
                    $customer_email = $this->session->data['guest']['email'];
                }
                if (isset($this->session->data['guest']['firstname']) && $this->session->data['guest']['firstname'] != "") {
                    $customer_firstname = $this->session->data['guest']['firstname'];
                }
                if (isset($this->session->data['guest']['lastname']) && $this->session->data['guest']['lastname'] != "") {
                    $customer_lastname = $this->session->data['guest']['lastname'];
                }
                if (isset($this->session->data['guest']['telephone']) && $this->session->data['guest']['telephone'] != "") {
                    $customer_phone = preg_replace('/\s/', '', $this->session->data['guest']['telephone']);
                }
            }
            $customer_firstname = $this->fixString($customer_firstname);
            $customer_lastname = $this->fixString($customer_lastname);
            $customer_email=str_replace(' ', '', mb_strtolower($customer_email));
            if ($customer_email !== "") {
                $advanced_matching_data[]="em: '".$customer_email."'";
            }
            if ($customer_firstname !== "") {
                $advanced_matching_data[]="fn: '".$customer_firstname."'";
            }
            if ($customer_lastname !== "") {
                $advanced_matching_data[]="ln: '".$customer_lastname."'";
            }
            if ($customer_phone !== "") {
                $advanced_matching_data[]="ph: '".$customer_phone."'";
            }
        }
        $script = "
!function(f,b,e,v,n,t,s)
{if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};
if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];
s.parentNode.insertBefore(t,s)}(window, document,'script',
'https://connect.facebook.net/en_US/fbevents.js');
fbq('init', '".$facebook_id."'".(!empty($advanced_matching_data) ? ", {".implode(',', $advanced_matching_data)."}" : "").");";
    return $script;
    }

    public function setFacebookScript($page_type = '', $products = array(), $order_id = '')
    {
        $facebook_id = $this->config->get('analytics_script_manager_facebook_id');
        if ((int)$this->config->get('analytics_script_manager_status') != 1 || $facebook_id == '') {
            return;
        }
        if (empty($products)) {
            $this->facebook_pid_list = array();
            $this->facebook_products = array();
        }
        //get settings
        $custom_products = (int)$this->config->get('analytics_script_manager_facebook_custom_products');
        $facebook_tax = (int)$this->config->get('analytics_script_manager_facebook_tax');
        $use_shipping = (int)$this->config->get('analytics_script_manager_facebook_shipping');
        $currency = $this->config->get('analytics_script_manager_facebook_currency');
        if ($currency === null) {
            $currency = $this->config->get('config_currency');
        } elseif ($currency === 'customer') {
            $currency = $this->session->data['currency'];
        }
        $total_value_facebook = "";
        $search_string = "";
        $name = $this->document->getTitle();//"Other";
        $name = ($name == "" ? ucfirst($page_type) : $name);
        $category = "";
        $content_type = "";
        $shipping_price = 0;

        if ($this->total_value != "") {
            if ($facebook_tax) {
                $total_value_facebook = $this->currency->format($this->total_value_tax, substr($currency, -3, 3),'',false);
            } else {
                $total_value_facebook = $this->currency->format($this->total_value, substr($currency, -3, 3),'',false);
            }
        }
        //set events
        $page_type_facebook = "ViewOther";
        $page_track_facebook = "trackCustom";
        $first_product = array();
        if (count($products) > 0) {
            $first_product = $products[0];
        } else {//dummy
            $first_product['name'] = $name;//$this->document->getTitle();
            $first_product['category'] = array('');
        }
        $category = $first_product['category'];
        if ($page_type == 'product') {
            $page_type_facebook = "ViewContent";
            $page_track_facebook = "track";
            $name = $first_product['name'];
            $content_type = "product_group";
        } elseif ($page_type == 'category') {
            $page_type_facebook = "ViewCategory";//custom
            $page_track_facebook = "trackCustom";
            $name = $first_product['category'][count($first_product['category'])-1];
            $content_type = "product_group";
        } elseif ($page_type == 'search') {
            $page_type_facebook = "Search";
            $page_track_facebook = "track";
            $search_string = $this->getSearch();
            $content_type = "product_group";
        } elseif ($page_type == 'cart') {
            $page_type_facebook = "ViewCart";//custom
            $page_track_facebook = "trackCustom";
            $content_type = 'product';
        } elseif ($page_type == 'checkout') {
            $page_type_facebook = "InitiateCheckout";
            $page_track_facebook = "track";
            $content_type = 'product';
        } elseif ($page_type == 'purchase') {
            $page_type_facebook = "Purchase";
            $page_track_facebook = "track";
            $this->load->model('checkout/order');
            $free_shipping = false;
            if (isset($this->session->data['coupon'])) {
                $this->load->model('extension/total/coupon');
                $coupon_info = $this->model_extension_total_coupon->getCoupon($this->session->data['coupon']);
                $free_shipping = $this->getShippingDiscount($coupon_info);
            }
            if ($use_shipping && !$free_shipping) {
                $shipping_price = $this->model_checkout_order->getOrderShipping($order_id);
                if ($facebook_tax && isset($this->session->data['shipping_method'])) {
                    $shipping_price = $this->tax->calculate($shipping_price, $this->session->data['shipping_method']['tax_class_id'], 1);
                }
                $shipping_price = $this->currency->format($shipping_price, $currency,'',false);
            }
            $content_type = 'product';
        } elseif ($page_type == 'home') {
            $page_type_facebook = "ViewHome";//custom
            $page_track_facebook = "trackCustom";
        } elseif ($page_type == 'login') {
            $page_type_facebook = "ViewLogin";//custom
            $page_track_facebook = "trackCustom";
        } elseif ($page_type == 'registration') {
            $page_type_facebook = "CompleteRegistration";
            $page_track_facebook = "track";
        }
        $quantity = 0;
        $count = 0;
        if ($custom_products || $page_track_facebook == "track") {
            $count = count($products);
            foreach ($products as $value) {
                $quantity += $value['quantity'];
            }
        }

        //set facebook pixel (only script version - no pixel)
        $script = "
fbq('track', 'PageView');
fbq('".$page_track_facebook."','".$page_type_facebook."',{
content_name: '".$this->fixString($name)."',"
.($count > 0 ? "
content_ids: ['".implode("','", $this->facebook_pid_list)."']," : "")
.($count > 0 && $content_type != "" ? "
content_type: '".$content_type."'," : "")
.($count > 0 ? "
contents: [{".implode('},{', $this->facebook_products)."}]," : "")
.($category[0] != "" ? "
content_category: '".$this->fixString(implode(" > ", $category))."'," :"")
.($search_string != "" ? "
search_string: '".$this->fixString($search_string)."'," :"")
.($count > 0 && $total_value_facebook != "" ? "
value: ".($total_value_facebook+$shipping_price).",
currency: '".substr($currency, 0, 3)."'," : "")
.($count > 0 && $quantity > 0 ? "
num_items: '".$quantity."'" : "")."});";
/*<noscript><img height=\"1\" width=\"1\" alt=\"\" style=\"display:none\"
src=\"https://www.facebook.com/tr?id=".$facebook_id."&ev=PageView&noscript=1\"
/></noscript>*/
        $this->session->data['scriptmanager']['facebook'] = html_entity_decode($script, ENT_QUOTES, 'UTF-8');
    }

    public function getFacebookClickScript($event_name = '', $product = array())
    {
        if ($this->config->get('analytics_script_manager_facebook_id')=='') {
            return '';
        }
        $currency = $this->config->get('analytics_script_manager_facebook_currency');
        if ($currency === null) {
            $currency = $this->config->get('config_currency');
        } elseif ($currency === 'customer') {
            $currency = $this->session->data['currency'];
        }
        $facebook_pid = "";
        $facebook_id_type = ($this->config->get('analytics_script_manager_facebook_pid') == 'copy' ? $this->config->get('feed_facebook_catalog_pid1') : $this->config->get('analytics_script_manager_facebook_pid'));
        if ($facebook_id_type == 'model') {
            $facebook_pid = $product['model'];
        } else {
            $facebook_pid = $product['product_id'];
        }
        $facebook_option_ids = ($this->config->get('analytics_script_manager_facebook_option_ids') == 'copy' ? $this->config->get('feed_facebook_catalog_option_ids') : $this->config->get('analytics_script_manager_facebook_option_ids'));
        $facebook_options = $this->getSettingOptionIDs('analytics_script_manager_facebook_options', 'feed_facebook_catalog_');//script setting name, feed prefix setting name
        $f_options = $this->getOptionsProduct($product, $facebook_options);
        $facebook_pid = $facebook_pid.$this->getOptionID($facebook_option_ids, $f_options);
        $price = $this->currency->format($this->tax->calculate($this->getPrice($product), $product['tax_class_id'], $this->config->get('analytics_script_manager_facebook_tax'))*$product['quantity'], substr($currency, -3, 3),'',false);
        $script = "fbq('track', '".$event_name."', {
content_name: '".$this->fixString($product['name'])."',
content_ids: '".$this->fixString($facebook_pid)."',
content_type: '".($event_name == 'AddToCart' ? "product" : "product_group")."',
contents: [{".$this->getFacebookProduct($facebook_pid, $product, $currency)."}],
value: ".$price.",
currency: '".substr($currency, 0, 3)."'
});";
        return html_entity_decode($script, ENT_QUOTES, 'UTF-8');
    }

    public function getGoogleClickScript($event_name = '', $product = array())
    {
        $adwords_id = $this->config->get('analytics_script_manager_adwords_id');
        $analytics_id = $this->config->get('analytics_script_manager_analytics_id');
        $via_analytics = (int)$this->config->get('analytics_script_manager_use_analytics');
        $via_merchant = (int)$this->config->get('analytics_script_manager_use_merchant');
        $ecommerce = (int)$this->config->get('analytics_script_manager_use_ecommerce');
        $is_legacy = (int)$this->config->get('analytics_script_manager_use_google_legacy');
        $google_option_ids = ($this->config->get('analytics_script_manager_google_option_ids') == 'copy' ? $this->config->get('feed_google_merchant_center_option_ids') : $this->config->get('analytics_script_manager_google_option_ids'));
        $google_options = $this->getSettingOptionIDs('analytics_script_manager_google_options', 'feed_google_merchant_center_');//script setting name, feed prefix setting name
        $g_options = $this->getOptionsProduct($product, $google_options);
        if ($adwords_id != '' && substr($adwords_id,0,1) !== 'A') {
            $adwords_id = 'AW-'.$adwords_id;
        }
        $currency = $this->config->get('analytics_script_manager_google_currency');
        if ($currency === null) {
            $currency = $this->config->get('config_currency');
        } elseif ($currency === 'customer') {
            $currency = $this->session->data['currency'];
        }
        $script = '';
        $this->setGoogleIDs($google_merchant_id1, $google_adwords_id1, $google_adwords_id2, $product);
        if ($ecommerce) {
            $script .= "gtag('event', '".$event_name."', {'send_to': '".$analytics_id."', 'event_label': '".$product['name']."', 'items': [{".$this->getEcommerceProduct($google_merchant_id1, $product, $currency)."}]});";
        }
        $price = $this->currency->format($this->tax->calculate($this->getPrice($product), $product['tax_class_id'], $this->config->get('analytics_script_manager_google_tax'))*$product['quantity'], $currency, '', false);
        if (!$is_legacy && $adwords_id != "" && ($via_analytics || $via_merchant)) {
            $script .= "gtag('event', '".$event_name."', {
'send_to': '".$adwords_id."',
'value': '".$price."',
'items': [".($via_analytics == 1 ? "{".$this->getAnalyticsProduct($google_adwords_id1, $google_adwords_id2)."}" : "" ).
($via_analytics == 1 && $via_merchant == 1 ? ",
" : "").
($via_merchant == 1 ? "{".$this->getMerchantProduct($google_merchant_id1.$this->getOptionID($google_option_ids, $g_options))."}" : "" )."]
});";
        }
        return html_entity_decode($script, ENT_QUOTES, 'UTF-8');
    }

    public function getCustomClickScript($product = array())
    {
        $file_scripts = $this->setTemplates();
        $script = $this->setScriptTag($this->config->get('analytics_script_manager_dynamic_cart_add'), 0);
        $script.= implode($this->loadTemplates($file_scripts, 'cart_add', 0));
        $script = $this->processReplace($script, array($product));
        return html_entity_decode($script, ENT_QUOTES, 'UTF-8');
    }

    protected function setGoogleIDs(&$google_merchant_id1, &$google_adwords_id1, &$google_adwords_id2, $product)
    {
        $google_merchant_id1 = '';
        $google_adwords_id1 = '';
        $google_adwords_id2 = '';
        $google_mpid1 = ($this->config->get('analytics_script_manager_google_pid1') == 'copy' ? $this->config->get('feed_google_merchant_center_pid1') : $this->config->get('analytics_script_manager_google_pid1'));
        $google_apid1 = ($this->config->get('analytics_script_manager_google_pid1') == 'copy' ? $this->config->get('feed_google_business_data_pid1') : $this->config->get('analytics_script_manager_google_pid1'));
        $google_apid2 = ($this->config->get('analytics_script_manager_google_pid2') == 'copy' ? $this->config->get('feed_google_business_data_pid2') : $this->config->get('analytics_script_manager_google_pid2'));
        if ($google_mpid1 == 'model') {
            $google_merchant_id1 = $product['model'];
        } else {
            $google_merchant_id1 = $product['product_id'];
        }
        if ($google_apid1 == 'model') {
            $google_adwords_id1 = $product['model'];
        } else {
            $google_adwords_id1 = $product['product_id'];
        }
        if ($google_apid2 == 'product_id') {
            $google_adwords_id2 = $product['product_id'];
        } elseif ($google_apid2 == 'model') {
            $google_adwords_id2 = $product['model'];
        }
    }

    protected function processReplace($script, $products = array(), $order_id = '', $page_type = '')
    {
        $script = $this->getDynamicReplace($script, $products, $order_id, $page_type);
        $script = $this->processCalculate($script);
        $script = $this->processRound($script);
        $script = $this->getDynamicCleaned($script);//clean must skip conditions #if# #is_set# #else#
        $script = $this->processCondition($script);
        return $script;
    }

    public function getCustomHeader()
    {
        $script = $this->setScriptTag($this->config->get('analytics_script_manager_dynamic_all'), 1);
        $file_scripts = $this->setTemplates();
        $script.= implode($this->loadTemplates($file_scripts, 'header', 1));
        $script = $this->processReplace($script);
        return html_entity_decode($script, ENT_QUOTES, 'UTF-8');
    }

    public function setDynamicScript($page_type = 'other', $products = array(), $order_id = '')
    {
        $script = '';
        $file_scripts = $this->setTemplates();
        $add_tags = (int)$this->config->get('analytics_script_manager_header_ajax');
        if ($page_type == 'product') {
            $script.= $this->setScriptTag($this->config->get('analytics_script_manager_dynamic_product'), $add_tags);
            $script.= implode($this->loadTemplates($file_scripts, 'product', $add_tags));
        } elseif ($page_type == 'category' || $page_type == 'search') {
            $script.= $this->setScriptTag($this->config->get('analytics_script_manager_dynamic_category'), $add_tags);
            $script.= implode($this->loadTemplates($file_scripts, $page_type, $add_tags));
        } elseif ($page_type == 'cart') {
            $script.= $this->setScriptTag($this->config->get('analytics_script_manager_dynamic_cart'), $add_tags);
            $script.= implode($this->loadTemplates($file_scripts, 'cart', $add_tags));
        } elseif ($page_type == 'checkout') {
            $script.= $this->setScriptTag($this->config->get('analytics_script_manager_dynamic_checkout'), $add_tags);
            $script.= implode($this->loadTemplates($file_scripts, 'checkout', $add_tags));
        } elseif ($page_type == 'purchase') {
            $script.= $this->setScriptTag($this->config->get('analytics_script_manager_dynamic_success'), $add_tags);
            $script.= implode($this->loadTemplates($file_scripts, 'purchase', $add_tags));
        } else {
            $script.= $this->setScriptTag($this->config->get('analytics_script_manager_dynamic_other'), $add_tags);
            $script.= implode($this->loadTemplates($file_scripts, $page_type, $add_tags));//enables extra page types (home, registration)
        }
        $script = $this->processReplace($script, $products, $order_id, $page_type);
        $script.= $this->setScriptTag($this->getDynamicButtons($file_scripts, $products), $add_tags);
        $script.= $this->sendApi($file_scripts, $products, $order_id, $page_type);
        $this->session->data['scriptmanager']['custom'] = html_entity_decode($script, ENT_QUOTES, 'UTF-8');
    }

    protected function getDynamicReplace($script, $products = array(), $order_id = '', $page_type = '')
    {
        if ($script == '') {
            return '';
        }
        $page_name = $this->fixString($this->document->getTitle());
        $currency = $this->config->get('analytics_script_manager_custom_currency');
        if ($currency === null) {
            $currency = $this->config->get('config_currency');
        } elseif ($currency === 'customer') {
            $currency = $this->session->data['currency'];
        } else {
            $currency = substr($currency, -3, 3);
        }
        $languages = $this->getUserLanguage($this->session->data['language']);
        $script = str_replace('#order_id#', $order_id, $script);
        $script = str_replace('#total_without_tax#', $this->currency->format((float)$this->total_value, $currency, '',false), $script);
        $script = str_replace('#total_with_tax#', $this->currency->format((float)$this->total_value_tax, $currency, '',false), $script);
        $script = str_replace('#total_tax#', $this->currency->format(((float)$this->total_value_tax-(float)$this->total_value), $currency, '',false), $script);
        $script = str_replace('#full_total_without_tax#', $this->currency->format((float)$this->total_full_value, $currency, '',false), $script);
        $script = str_replace('#full_total_with_tax#', $this->currency->format((float)$this->total_full_value_tax, $currency, '',false), $script);
        $script = str_replace('#full_total_tax#', $this->currency->format(((float)$this->total_full_value_tax-(float)$this->total_full_value), $currency, '',false), $script);
        $script = str_replace('#currency#', $currency, $script);
        $script = str_replace('#user_language_locale#', $languages['locale'], $script);
        $script = str_replace('#user_language_name#', $languages['name'], $script);
        $script = str_replace('#user_language_iso#', $languages['iso'], $script);
        $script = str_replace('#page_name#', ($page_name == "" ? ucfirst($page_type) : $page_name), $script);
        $quantity = 0;
        foreach ($products as $value) {
            $quantity+=(int)$value['quantity'];
        }
        $script = str_replace('#total_quantity#', $quantity, $script);
        //product list processing #product_start #product_end
        $sequence = $this->explodeTemplateSequence($script, 'product');
        while ($sequence !== false) {
            $before = $sequence['before'];
            $center = $sequence['center'];
            $after = $sequence['after'];
            $delimiter = $sequence['delimiter'];
            $product_list = array();
            foreach ($products as $value) {
                $product_list[]= $this->getDynamicProduct($center, $value, $currency);
            }
            $script = $before.implode($delimiter, $product_list).$after;
            $sequence = $this->explodeTemplateSequence($script, 'product');
        }
        if (!empty($products)) {
            $script = $this->getDynamicProduct($script, $products[0], $currency);//single product
        }
        //user data
        $customer_email='';
        $customer_firstname='';
        $customer_lastname='';
        $customer_phone='';
        if ($this->customer->isLogged()){
            $customer_email = mb_strtolower($this->customer->getEmail());
            $customer_firstname = mb_strtolower($this->customer->getFirstName());
            $customer_lastname = mb_strtolower($this->customer->getLastName());
            $customer_phone = mb_strtolower(preg_replace('/\s/', '', $this->customer->getTelephone()));
        } elseif (isset($this->session->data['guest'])){
            if (isset($this->session->data['guest']['email']) && $this->session->data['guest']['email'] != "") {
                $customer_email = $this->session->data['guest']['email'];
            }
            if (isset($this->session->data['guest']['firstname']) && $this->session->data['guest']['firstname'] != "") {
                $customer_firstname = $this->session->data['guest']['firstname'];
            }
            if (isset($this->session->data['guest']['lastname']) && $this->session->data['guest']['lastname'] != "") {
                $customer_lastname = $this->session->data['guest']['lastname'];
            }
            if (isset($this->session->data['guest']['telephone']) && $this->session->data['guest']['telephone'] != "") {
                $customer_phone = preg_replace('/\s/', '', $this->session->data['guest']['telephone']);
            }
        }
        $customer_firstname = $this->fixString($customer_firstname);
        $customer_lastname = $this->fixString($customer_lastname);
        $customer_email=str_replace(' ', '', mb_strtolower($customer_email));
        $script = str_replace('#email#', $customer_email, $script);
        $script = str_replace('#first_name#', $customer_firstname, $script);
        $script = str_replace('#last_name#', $customer_lastname, $script);
        $script = str_replace('#phone#', $customer_phone, $script);
        return $script;
    }

    protected function getDynamicProduct($script, $product, $currency)
    {
        $price_without_tax = $this->tax->calculate($this->getPrice($product), $product['tax_class_id'], 0);
        $price_with_tax = $this->tax->calculate($this->getPrice($product), $product['tax_class_id'], 1);
        $tax = $price_with_tax - $price_without_tax;
        $full_price_with_tax = $this->tax->calculate((float)$product['price'], $product['tax_class_id'], 1);
        $full_price_without_tax = $this->tax->calculate((float)$product['price'], $product['tax_class_id'], 0);
        $full_tax = $full_price_with_tax - $full_price_without_tax;
        $script = str_replace('#product_id#', $product['product_id'], $script);
        $script = str_replace('#model#', $this->fixString($product['model']), $script);
        $script = str_replace('#product_name#', $this->fixString($product['name']), $script);
        $script = str_replace('#price_with_tax#', $this->currency->format($price_with_tax, $currency, '',false) , $script);
        $script = str_replace('#price_without_tax#', $this->currency->format($price_without_tax, $currency, '',false) , $script);
        $script = str_replace('#price_tax#', $this->currency->format($tax, $currency, '',false) , $script);
        $script = str_replace('#full_price_with_tax#', $this->currency->format($full_price_with_tax, $currency, '',false) , $script);
        $script = str_replace('#full_price_without_tax#', $this->currency->format($full_price_without_tax, $currency, '',false) , $script);
        $script = str_replace('#full_price_tax#', $this->currency->format($full_tax, $currency, '',false) , $script);
        $script = str_replace('#manufacturer#', $this->fixString($product['manufacturer']), $script);
        $script = str_replace('#search#', $this->fixString($this->getSearch()), $script);
        $script = str_replace('#quantity#', $product['quantity'], $script);
        //simple category list, might be improved by getting more category data
        $category_sequence = $this->explodeTemplateSequence($script, 'product_category');
        while ($category_sequence !== false) {
            $categories = array();
            foreach ($product['category'] as $category) {//update to include more category data if needed
                $categories[]= str_replace('#category_name#', $category, $category_sequence['center']);
            }
            $categories = array_unique($categories);
            $script = $category_sequence['before'].implode($category_sequence['delimiter'], $categories).$category_sequence['after'];
            $category_sequence = $this->explodeTemplateSequence($script, 'product_category');
        }
        $script = str_replace('#category_breadcrumb#', $this->fixString(implode("/", $product['category'])), $script);
        $script = str_replace('#category_name#', $this->fixString($product['category'][count($product['category'])-1]), $script);
        //use only selected options
        $selected_options = $this->getSettingOptionIDs('analytics_script_manager_custom_options', '');
        $variant_options = array();
        if (isset($product['option']) && is_array($product['option'])) {
            foreach ($product['option'] as $option) {
                if (in_array($option['option_id'], $selected_options)) {
                    $variant_options[$option['option_value_id']] = $option;
                }
            }
            ksort($variant_options);
        }
        $sequence = $this->explodeTemplateSequence($script, 'product_option');
        while ($sequence !== false) {
            $before = $sequence['before'];
            $center = $sequence['center'];
            $after = $sequence['after'];
            $delimiter = $sequence['delimiter'];
            $list = array();
            foreach ($variant_options as $value) {
                $option = $center;
                $option = str_replace('#option_id#', $value['option_id'], $option);
                $option = str_replace('#option_value_id#', $value['option_value_id'], $option);
                $option = str_replace('#option_name#', $value['name'], $option);
                $option = str_replace('#option_value#', $value['value'], $option);
                $list[] = $option;
            }
            $list = array_unique($list);
            $script = $before.implode($delimiter, $list).$after;
            $sequence = $this->explodeTemplateSequence($script, 'product_option');
        }
        //first value if product_option_start is omitted
        $first = reset($variant_options);
        if ($first !== false) {
            $script = str_replace('#option_id#', $first['option_id'], $script);
            $script = str_replace('#option_value_id#', $first['option_value_id'], $script);
            $script = str_replace('#option_name#', $first['name'], $script);
            $script = str_replace('#option_value#', $first['value'], $script);
        }
        //specific & simple
        $options = array();
        $id = $product['product_id'];
        foreach ($variant_options as $value) {
            $id .= '-'.$value['option_value_id'];
            $options[] = $value['value'];
            $key = $value['option_id'];
            $script = str_replace('#option_value_'.$key.'#', $value['value'], $script);
            $script = str_replace('#option_value_id_'.$key.'#', $value['option_value_id'], $script);
        }
        $script = str_replace('#variations#', implode(',', $options), $script);
        $script = str_replace('#id#', $id, $script);
        return $script;
    }

    protected function getDynamicCleaned($script)
    {
        $script = str_replace('<script></script>', '', $script);
        $script = str_replace('#product_id#', "", $script);
        $script = str_replace('#model#', "", $script);
        $script = str_replace('#product_name#', "", $script);
        $script = str_replace('#price_with_tax#', "" , $script);
        $script = str_replace('#price_without_tax#', "" , $script);
        $script = str_replace('#price_tax#', "" , $script);
        $script = str_replace('#full_price_with_tax#', "" , $script);
        $script = str_replace('#full_price_without_tax#', "" , $script);
        $script = str_replace('#full_price_tax#', "" , $script);
        $script = str_replace('#manufacturer#', "", $script);
        $script = str_replace('#product_category_list#', "", $script);
        $script = str_replace('#category_breadcrumb#', "", $script);
        $script = str_replace('#category_name#', "", $script);
        $script = str_replace('#search#', "", $script);
        $script = str_replace('#quantity#',"", $script);
        $script = str_replace('#total_quantity#',"", $script);
        $script = str_replace("#product_list#", "",$script);
        $script = str_replace("#product_option_list#", "",$script);
        $script = str_replace("#product_start#", "",$script);
        $script = str_replace("#product_end#", "",$script);
        $script = str_replace("#product_option_start#", "",$script);
        $script = str_replace("#product_option_end#", "",$script);
        $script = str_replace('#variations#', "", $script);
        $script = str_replace('#id#', "", $script);
        $script = str_replace('#option_id#', "", $script);
        $script = str_replace('#option_value_id#', "", $script);
        $script = str_replace('#option_name#', "", $script);
        $script = str_replace('#option_value#', "", $script);
        $script = str_replace('#calculate#', "", $script);
        $script = str_replace('#round#', "", $script);
        $script = str_replace('#precision#', "", $script);
        $script = str_replace('#user_language_locale#', "", $script);
        $script = str_replace('#user_language_name#', "", $script);
        $script = str_replace('#user_language_iso#', "", $script);
        $script = preg_replace('/#option_value_[\\d]+#/', '', $script);
        $script = preg_replace('/#option_value_id_[\\d]+#/', '', $script);
        $script = preg_replace('/#[\\w| ]+_text_input#/', '', $script);
        return $script;
    }

    protected function explodeTemplateSequence($template, $sequence_name)
    {
        //simplified list
        if (strpos($template, '_start#')) {//backwards compatibility
            $append_start = '_start#';
            $sequence_start = '#'.$sequence_name.'_start#';
            $sequence_end = '#'.$sequence_name.'_end#';
            $start_len = strlen($sequence_start);
            $end_len = strlen($sequence_end);
        } else {
            $append_start = '_list#';
            $sequence_start = '#'.$sequence_name.'_list#';
            $sequence_end = $sequence_start;
            $start_len = strlen($sequence_start);
            $end_len = $start_len;
        }

        $start = strpos($template, $sequence_start);
        if ($start !== false) {//only first
            $end = strpos($template, $sequence_end, $start+$start_len);
            $template_center = substr($template, $start+$start_len, $end-($start+$start_len));
            $template_start = substr($template, 0, $start);
            $template_end = substr($template, $end + $end_len);
            $delimiter = strpos($template_center, '#delimiter#');
            $next_start = strpos($template_center, $append_start);
            if ($delimiter !== false && ($next_start === false || $delimiter < $next_start)) {
                $delimiter = substr($template_center, 0, $delimiter);
                $template_center = substr($template_center, strlen($delimiter.'#delimiter#'));
            } else {
                $delimiter = ",";//default
            }
            return array(
                'before' => $template_start,
                'center' => $template_center,
                'after' => $template_end,
                'delimiter' => $delimiter
            );
        } else {
            return false;
        }
    }

    protected function fixString($string)
    {
        return str_replace("'", "\'", str_replace('"', '\"', $string));
        //return str_replace('&quot;', '',str_replace('&apos;', '',str_replace('"', '',str_replace("'", "",$string))));
    }

    public function getCategoryBreadcrumb($breadcrumb, $start = 1)
    {
        if (!is_array($breadcrumb)) {
            return array($breadcrumb);
        }
        $category = array();
        foreach ($breadcrumb as $key => $value) {
            if ((int)$key >= $start) {
                $category[]=$value['text'];
            }
        }
        if (empty($category)) {
            return array('');
        }
        return $category;
    }

    public function getManufacturer($product_id)
    {
        $query = $this->db->query("SELECT `m`.`name` AS `manufacturer` FROM `".DB_PREFIX."manufacturer` AS `m` LEFT JOIN `".DB_PREFIX."product` AS `p` ON `p`.`manufacturer_id` = `m`.`manufacturer_id` WHERE `p`.`product_id` = ".$product_id);
        if (isset($query->row['manufacturer'])) {
            return $query->row['manufacturer'];
        }
        return '';
    }

    public function getSearch()
    {
        $search_string = "";
        if (isset($this->request->get['search'])) {
            $search_string=$this->request->get['search'];
        }
        return $search_string;
    }

    public function getProductOption($product_option_value_id)//get product options if not set in opencart, used in ocmod
    {
        $query = $this->db->query("SELECT `opvd`.`option_value_id` AS `option_value_id`,`opvd`.`name` AS `value`, `opvd`.`option_id` AS `option_id`, `od`.`name` AS `name`
FROM `".DB_PREFIX."product_option_value` AS `pov`
INNER JOIN `".DB_PREFIX."option_value_description` AS `opvd`
ON `pov`.`option_value_id`=`opvd`.`option_value_id`
INNER JOIN `".DB_PREFIX."option_description` AS `od`
ON `od`.`option_id`=`opvd`.`option_id`
WHERE `pov`.`product_option_value_id` = ".(int)$product_option_value_id." AND `opvd`.`language_id` = ".(int)$this->config->get('config_language_id')."
GROUP BY `opvd`.`option_value_id`
ORDER BY `opvd`.`option_value_id` ASC;");
        return ($query->rows ? $query->row : null);
    }

    public function getProductDiscount($products, $index, $sub_total, $coupon_info = 0)
    {
        if ($coupon_info) {
            if ($coupon_info['product']) {
                $sub_total = 0;
                foreach ($products as $product) {
                    if (in_array($product['product_id'], $coupon_info['product'])) {
                        $sub_total += $this->getPrice($product);
                    }
                }
            }

            if ($coupon_info['type'] == 'F') {
                $coupon_info['discount'] = min($coupon_info['discount'], $sub_total);
            }
            $discount = 0;
            $price = $this->getPrice($products[$index]);
            if (!$coupon_info['product']) {
                $status = true;
            } else {
                $status = in_array($products[$index]['product_id'], $coupon_info['product']);
            }
            if ($status) {
                if ($coupon_info['type'] == 'F') {
                    $discount = $coupon_info['discount'] * ($price/ $sub_total);
                } elseif ($coupon_info['type'] == 'P') {
                    $discount = $price / 100 * $coupon_info['discount'];
                }
            }
            if ($discount > $price) {
                $discount = $price;
            }
            return $discount;
        }
        return 0;
    }

    public function getShippingDiscount($coupon_info = 0)
    {
        if ($coupon_info) {
            if ($coupon_info['shipping'] && isset($this->session->data['shipping_method'])) {
                return true;
            }
        }
        return false;
    }

    public function getOrderSubTotal($order_id)
    {
        $query = $this->db->query("SELECT `value`
FROM `".DB_PREFIX."order_total`
WHERE `order_id` = '".(int)$order_id."' AND `code` = 'sub_total';");
        if (isset($query->row['value'])) {
            return $query->row['value'];
        }
        return 0;
    }

    protected function getSettingOptionIDs($script_setting_name, $feed_prefix_name)//get all options selected in settings
    {
        $options = array(
            $this->config->get($script_setting_name),//script options
            $this->config->get($feed_prefix_name.'size_options'),//feed options
            $this->config->get($feed_prefix_name.'color_options'),//feed options
            $this->config->get($feed_prefix_name.'pattern_options'),//feed options
            $this->config->get($feed_prefix_name.'material_options')//feed options
        );
        $optionIDs = array();
        foreach ($options as $value) {
            if (!is_array($value)) {
                if (substr($value, 0, 1) === '[') {
                    $value = json_decode($value);
                } else {
                    $value = array();
                }
            }
            $optionIDs = array_merge($optionIDs, $value);
        }
        $optionIDs = array_unique($optionIDs);
        $options = array();
        foreach ($optionIDs as $o_id) {
            if (substr($o_id, 0, 1) !== 'a') {//is not attribute
                $options[]=str_replace('o', '', $o_id);
            }
        }
        return $options;
    }

    protected function getOptionsProduct($product, $setting_option_ids)//get options for product which are selected in settings
    {
        $options = array();
        if (isset($product['option']) && is_array($product['option'])) {
            foreach ($product['option'] as $option) {
                if (in_array($option['option_id'], $setting_option_ids)) {
                    $options[$option['option_value_id']] = $option['value'];
                }
            }
            ksort($options);
        }
        return $options;
    }

    protected function getOptionID($option_type, $options_product, $sep = '-')//get option id string for product, getSettingOptionIDs->getOptionsProduct->getOptionID
    {
        $option_ids = array();
        if ($option_type == "option_id") {
            foreach ($options_product as $option_value_id => $value) {
                $option_ids[]=$option_value_id;
            }
        } elseif ($option_type == "option_name") {
            foreach ($options_product as $option_value_id => $value) {
                $option_ids[]=str_replace(' ', '_', $value);
            }
        }
        return (count($option_ids) ? $sep.implode($sep, $option_ids) : "");
    }

    private function processCalculate($template)
    {
        $start = strpos($template, '#calculate#');
        while ($start !== false) {
            $len = strlen('#calculate#');
            $end = strpos($template, '#calculate#', $start+$len);
            $equation = substr($template, $start+$len, $end-($start+$len));
            $equation = $this->calculate($equation);
            $template = substr($template, 0, $start).$equation.substr($template, $end+$len);
            $start = strpos($template, '#calculate#');
        }
        return $template;
    }

    private function calculate($equation)
    {
        //fix small issues
        $equation = str_replace(',', '.', $equation);
        $equation = str_replace(' ', '', $equation);
        $result = (float)$equation;
        //calculate / *
        while(preg_match('/(\-?[\d\.\s]+)([\*\/])(\-?[\d\.\s]+)/', $equation, $matches) !== false && count($matches) === 4){
            $operator = $matches[2];
            switch($operator) {
                case '*':
                    $result = (float)$matches[1] * (float)$matches[3];
                    break;
                case '/':
                    $result = (float)$matches[1] / (float)$matches[3];
                    break;
            }
            //replace the partial result
            $pos = strpos($equation, $matches[0]);
            if ($pos !== false && $equation !== $matches[0]) {
                $equation = substr_replace($equation, $result, $pos, strlen($matches[0]));
            } else {//it's finished or something went wrong, anyway return result
                return $result;
            }
        }
        //calculate +-
        while(preg_match('/(\-?[\d\.\s]+)([\+\-])(\-?[\d\.\s]+)/', $equation, $matches) !== false && count($matches) === 4){
            $operator = $matches[2];
            switch($operator){
                case '+':
                    $result = (float)$matches[1] + (float)$matches[3];
                    break;
                case '-':
                    $result = (float)$matches[1] - (float)$matches[3];
                    break;
            }
            //replace the partial result
            $pos = strpos($equation, $matches[0]);
            if ($pos !== false && $equation !== $matches[0]) {
                $equation = substr_replace($equation, $result, $pos, strlen($matches[0]));
            } else {//it's finished or something went wrong, anyway return result
                return $result;
            }
        }
        return $result;
    }

    private function processRound($template)
    {
        $start = strpos($template, '#round#');
        while ($start !== false) {
            $len = strlen('#round#');
            $end = strpos($template, '#round#', $start+$len);
            $explode = explode('#precision#', substr($template, $start+$len, $end-($start+$len)));
            if (count($explode) === 2) {
                //fix small issues
                $num = str_replace(',', '.', $explode[1]);
                $num = str_replace(' ', '', $num);
                //round
                $result = round((float)$num, (int)$explode[0]);
            } else {
                $result = round(reset($explode));
            }
            $template = substr($template, 0, $start).$result.substr($template, $end+$len);
            $start = strpos($template, '#round#');
        }
        return $template;
    }

    private function processCondition($template)
    {
        $start = strpos($template, '#if#');
        while ($start !== false) {
            $len = strlen('#if#');
            $end = strpos($template, '#if#', $start+$len);
            $explode = explode('#is_set#', substr($template, $start+$len, $end-($start+$len)));
            $result = '';
            if (count($explode) === 2) {
                $condition = reset($explode);
                $else = explode('#else#', end($explode));
                if ($condition === '') {//remove condition
                    if (count($else) === 2) {//if else used keep else vlaue, otherwise use empty value
                        $result = end($else);
                    }
                } else {//keep condition
                    $result = reset($else);//keep first
                }
            } else {//something is wrong, use the last value
                $result = end($explode);
            }
            $template = substr($template, 0, $start).$result.substr($template, $end+$len);
            $start = strpos($template, '#if#');
        }
        return $template;
    }

    public function setTemplates()
    {
        $file_scripts = array();
        $template_location = trim($this->config->get('analytics_script_manager_template_location'), ' '.DIRECTORY_SEPARATOR);
        if (empty($template_location)) {
            $template_location = 'script_templates';
        }
        $root_folder = str_replace('catalog/', '', DIR_APPLICATION).$template_location;
        if (is_dir($root_folder)) {
            $templates = scandir($root_folder);
            foreach ($templates as $name) {
                if ($name != 'index.php' && substr($name, -4) === '.php') {
                    $scripts = null;
                    include($root_folder.'/'.$name);
                    if (isset($scripts)) {
                        $file_scripts[$name]=$scripts;
                    }
                }
            }
            return $file_scripts;
        }
        return array();
    }

    private function loadTemplates($scripts, $type, $add_tag = 0)
    {
        $templates = array();
        foreach ($scripts as $key => $value) {
            $setting_name = $this->unifyScriptName($key);
            $temp_type = $type;
            if ($type !== 'header') {//if not found use the other/category pages script
                if ($type === 'search' && !array_key_exists('search', $value) && array_key_exists('category', $value)) {
                    $temp_type = 'category';
                } else if (!array_key_exists($type, $value)) {
                    $temp_type = 'other';
                }
            }
            if (array_key_exists($temp_type, $value)) {
                $script = $this->replaceAccountID($value[$temp_type], $setting_name);
                $templates[$key] = $this->setScriptTag($script, $add_tag);
            }
        }
        return $templates;
    }

    private function getDynamicButtons($file_scripts, $products)
    {
        $script = '';
        //load buttons
        $loadedButtons = array();
        foreach ($file_scripts as $key => $value) {//each template file
            $setting_name = $this->unifyScriptName($key);
            if (array_key_exists('buttons', $value)) {//if uses buttons
                foreach ($value['buttons'] as $button_id => $button) {//each button
                    $loadedButtons[$button_id][] = $this->replaceAccountID($button, $setting_name);
                }
            }
        }
        //process buttons replace
        $button_scripts = array();
        foreach ($loadedButtons as $button_id => $buttons) {//each button id
            $button_script = '';
            foreach ($buttons as $button) {//each button
                $button_script.= $this->processReplace($button, $products);
            }
            $button_script = $this->setScriptTag($button_script, 0);//remove <script></script> if found
            $script.= "var buttons = document.querySelectorAll('".$button_id."');
    buttons.forEach(function(buttonScript) {
        buttonScript.addEventListener('click', function() {".$button_script."})
    });";
        }
        //buttons must be set after the page was loaded
        if ((int)$this->config->get('analytics_script_manager_header_ajax') && $script !== '') {
            $script = "if (typeof jQuery === 'undefined') {
    document.addEventListener('DOMContentLoaded', function(event) { ".$script."});
} else {
    $(document).ready(function() {".$script."});
}";
        }
        return $script;
    }

    private function sendApi($file_scripts, $products, $order_id, $page_type)
    {
        $debug = 0;//enable api console debug log
        $curl_return = '';
        if (in_array('curl', get_loaded_extensions())) {//curl available
            //load urls
            $urls = array();
            foreach ($file_scripts as $key => $value) {//each template file
                $setting_name = $this->unifyScriptName($key);
                if (array_key_exists('api', $value) && array_key_exists($page_type, $value['api'])) {//if uses api
                    foreach ($value['api'][$page_type] as $url) {
                        $url = $this->replaceAccountID($url, $setting_name);
                        $urls[]= $url;
                    }
                }
            }
            if (!empty($urls)) {
                $curl = curl_init();
                foreach ($urls as $url) {
                    $url = $this->processReplace($url, $products, $order_id, $page_type);
                    //call the url
                    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
                    curl_setopt($curl, CURLOPT_URL, $url);
                    if ($debug) {
                        $curl_return.= $this->setScriptTag("console.log('".curl_exec($curl)."');", (int)$this->config->get('analytics_script_manager_header_ajax'));
                    } else {
                        curl_exec($curl);
                    }
                }
                curl_close($curl);
            }
        }
        return $curl_return;
    }

    private function replaceAccountID($script, $name)
    {
        preg_match_all('/#[\\w| ]+_text_input#/', $script, $matches);
        foreach (reset($matches) as $value) {
            $key = str_replace('_text_input', '', str_replace('#', '', $value));
            $key_explode = explode('|', $key);//remove simple title for admin section if present
            $key = 'analytics_script_manager_custom_'.$name.'_'.mb_strtolower(end($key_explode));
            $account_id = $this->config->get($key);
            $script = str_replace($value, $account_id, $script);
        }
        return $script;
    }

    private function unifyScriptName($name)//convert script file name to a settings format name
    {
        return preg_replace('/[^a-z0-9_]/', '', mb_strtolower(str_replace(' ', '_', str_replace('.php', '', $name))));
    }

    private function setScriptTag($script, $add = 1, $do_not_track = 0)
    {
        $script = html_entity_decode($script, ENT_QUOTES, 'UTF-8');
        if ($script == "") {
            return $script;
        }
        if ($add) {//add tag
            if (!$this->hasScriptTag($script)) {
                if ($do_not_track) {
                    $script = 'if (typeof doNotTrackMe !== "function" || !doNotTrackMe()) {'.$script.'}';
                }
                return '<script>'.$script.'</script>';
            }
        } else {//remove tag
            if ($this->hasScriptTag($script)) {
                $script = strip_tags($script);
            }
            if ($do_not_track) {
                $script = 'if (typeof doNotTrackMe !== "function" || !doNotTrackMe()) {'.$script.'}';
            }
        }
        return $script;
    }

    private function hasScriptTag($script)
    {
        return (strpos($script, 'script>') !== false || strpos($script, '<script') !== false || strpos($script, 'script&gt') !== false || strpos($script, '&lt;script') !== false);
    }

    private function getUserLanguage($code)
    {
        $language = array('locale' => '', 'iso' => '', 'name' => '');
        $query = $this->db->query("SELECT `locale`, `name`
FROM `".DB_PREFIX."language`
WHERE `code` = '".$code."';");
        if ($query->row) {
            //try to find locale string
            $locales = explode(',', $query->row['locale']);
            foreach ($locales as $value) {
                if (strpos($value, '_') !== false && strpos($value, '.') === false) {
                    $language['locale'] = $value;
                    break;
                }
            }
            //try to find iso code
            $iso = preg_split('/[_-]/', $code);
            $language['iso'] = reset($iso);
            //language name
            $language['name'] = $query->row['name'];
        }
        return $language;
    }

    protected function getPrice($product)
    {
        $use_special_price = true;//change to setting
        $price = 0;
        if ((float)$product['special'] && $use_special_price) {
            $price = (float)$product['special'];
        } elseif(($this->config->get('config_customer_price') && $this->customer->isLogged()) || !$this->config->get('config_customer_price')) {
            $price = (float)$product['price'];
        }
        return $price;
    }
}
