<?php
class ModelUniversalFeedGoogleMerchant extends Model {

  public function writeHeader($fh, $config) {
    fwrite($fh, '<?xml version="1.0" encoding="UTF-8"?><rss xmlns:g="http://base.google.com/ns/1.0" version="2.0">'. "\n".
                '<channel>'."\n\t".
                '<title><![CDATA['.$this->config->get('config_name').']]></title>'."\n\t".
                '<link><![CDATA['.$this->config->get('config_url').']]></link>'."\n");
  }
  
  public function writeFooter($fh) {
    fwrite($fh, "\n</channel>\n</rss>");
  }
  
  public function writeBody($fh, $config) {
    ini_set('display_errors', 0);
    $config['filter_store'] = $this->config->get('config_store_id');
    $config['get_coupon'] = true;
    
    $config['optionAsArray'] = true;
    
    if (!empty($config['option_size']) || !empty($config['option_color'])) {
      $config['option_row'] = false;
    }
    
    $items = $this->model_universal_feed_driver_product->getItems($config);
    
    //$items = $this->model_tool_universal_feed->getProducts($config);

    $price_modifier = !empty($config['price_modifier']) ? $config['price_modifier'] : 1;
    $currency = !empty($config['currency']) ? $config['currency'] : 'USD';
    $gtin = !empty($config['gtin']) ? $config['gtin'] : '';
    $id_field = !empty($config['id']) ? $config['id'] : '';

    $row = 0;
    $save_count = 0;

    foreach ($items as $item) {
      if ($this->config->get('univfeed_sleep')) {
        usleep((int) $this->config->get('univfeed_sleep') * 1000); // 1 000 000 = 1s
      }
      
      $this->session->data['ufeed_lastItem'] = $item['product_id'];
      
      $gid = !empty($item[$id_field]) ? $item[$id_field] : $item['model'];
      
      $desc = $this->model_tool_universal_feed->truncate($this->model_tool_universal_feed->sanitize($item['description']), 5000);
      
      // use meta description if description is empty
      if (!$desc) {
        $desc = $item['meta_description'];
      }
      
      // use attributes if meta description is empty
      if (!$desc) {
        $attributes = explode('|', $item['product_attribute']);
        foreach ($attributes as $attribute) {
          $attr = explode(':', $attribute);
          if (isset($attr[1]) && isset($attr[2])) {
            $desc .= $attr[1] . ': ' . $attr[2] . " \n";
          }
        }
      }
      
      if ($item['image']) {
        if (true) {
          $image = HTTP_SERVER . 'image/' . $item['image_path'];
        } else {
          $image = @$this->model_tool_image->resize($item['image_path'], 1000, 1000);
        }
      } else {
        $image = @$this->model_tool_image->resize('no_image.jpg', 500, 500);
      }
      
      $stock = $item['quantity'] ? 'in stock' : 'out of stock';
      
      if ($item['date_available'] > date('Y-m-d')) {
        $stock = 'preorder';
      }
      
      if(!empty($config['multipack']) && $config['multipack'] == 1 && !empty($item['upc'])){
        $multipack = $item['upc'];
      } else {
        $multipack = 0;
      }

      // which price to show?
      $price_order = !empty($config['price_order']) ? explode('_', $config['price_order']) : array('special', 'discount', 'price');
      
      foreach ($price_order as $p) {
        if ($item[$p]) {
          $price_value = $item[$p];
          break;
        } 
      }
      
      $special_price = '';

      if($multipack !== 0){
        $price_value = $price_value * $multipack;
      }

      if($multipack !== 0 && !empty($item['special'])){
        $item['special'] = $item['special'] * $multipack;
      }
      
      if (empty($config['price_tax'])) {
        $price = $this->currency->format($this->tax->calculate($price_value * $price_modifier, $item['tax_class_id']), $currency, false, false);
        
        if (!empty($item['special'])) {
          $special_price = $this->currency->format($this->tax->calculate($item['special'] * $price_modifier, $item['tax_class_id']), $currency, false, false);
        }
      } else {
        $price = $this->currency->format($price_value * $price_modifier, $currency, false, false);
        
        if (!empty($item['special'])) {
          $special_price = $this->currency->format($item['special'] * $price_modifier, $currency, false, false);
        }
      }
      
      $formattedWeight = $this->weight->format($item['weight'], false);
      $realWeight = $this->weight->convert($item['weight'], $item['weight_class_id'], $this->config->get('config_weight_class_id'));
      
      $title = ($multipack !== 0) ? $multipack . ' ' . $item['name'] : $item['name'];

      if(!empty($config['title_suffix'])){
        $title = $title . ' ' . $config['title_suffix'];
      }

      $line = array(
        'g:id' => $gid,
        'g:title' => $title,
        'g:description' => $desc,
        'g:link' => $this->url->link('product/product', 'product_id=' . $item['product_id'] . (!empty($config['force_currency']) ? '&currency='.$currency : '')),
        'g:image_link' => $image,
        'g:condition' => 'new', // new, used, refurbished
        'g:availability' => $stock, // preorder, in stock, out of stock
        'g:price' => $price . ' ' . $currency,
        'g:shipping_weight' => $formattedWeight . ' ' . $this->weight->getUnit($item['weight_class_id']),
      );
      
      if (!empty($special_price)) {
        $line['g:sale_price'] = $special_price . ' ' . $currency;
      }
      
      if($multipack !== 0){
        $line['g:multipack'] = $item['upc'];
      }
      
      if ($item['length'] != 0) {
        $line['g:shipping_length'] = $this->length->format($item['length'], false) . ' ' . $this->length->getUnit($item['length_class_id']);
      }
      
      if ($item['width'] != 0) {
        $line['g:shipping_width'] = $this->length->format($item['width'], false) . ' ' . $this->length->getUnit($item['length_class_id']);
      }
      
      if ($item['height'] != 0) {
        $line['g:shipping_height'] = $this->length->format($item['height'], false) . ' ' . $this->length->getUnit($item['length_class_id']);
      }
      
			// 2 of the following 3 attributes are required fot this item according to the Unique Product Identifier Rules
      $has_identifier = 0;
      
      if (!empty($item[$gtin])) {
        $has_identifier++;
        $line['g:gtin'] = $item[$gtin];
      }
      
      if ($item['manufacturer']) {
        $has_identifier++;
        $line['g:brand'] = $item['manufacturer'];
      }
      
      if ($item['mpn']) {
        $has_identifier++;
        $line['g:mpn'] = $item['mpn'];
      }
			
      if(!empty($config['identifier_exist'])){
      if ($has_identifier < 2) {
        $line['g:identifier_exists'] = 'FALSE';
        } else {
          $line['g:identifier_exists'] = 'TRUE';
        }
      }
      
      if (true) {
        $category = $this->getGoogleCategory($item['product_id']);
        
        if (!empty($category['id'])) {
          $line['g:google_product_category'] = $category['id'];
        }
      } else {
        // get full name instead of ID, seems facebook prefer like this
        $category = $this->getGoogleCategoryByName($item['product_id']);
        
        if (!empty($category['name'])) {
          $line['g:google_product_category'] = $category['name'];
        }
      }
      
      // set category specific data
      if (!empty($category['id'])) {
        // Apparel & Accessories
        if (in_array($category['id'], array('166',' 1604',' 5322',' 5697',' 3128',' 3455',' 3188',' 6087',' 3729',' 5378',' 499979',' 3951',' 5460',' 5462',' 5461',' 5552',' 5379',' 5517',' 6006',' 7003',' 5463',' 5555',' 182',' 5408',' 5549',' 5424',' 5425',' 5622',' 5412',' 5423',' 5409',' 5410',' 5411',' 5621',' 2271',' 5182',' 5250',' 5490',' 7132',' 203',' 5506',' 5598',' 5514',' 3066',' 5909',' 1831',' 7313',' 204',' 212',' 207',' 1581',' 5344',' 208',' 5713',' 5513',' 2580',' 2302',' 1594',' 5183',' 1516',' 1580',' 211',' 5388',' 6031',' 5674',' 6227',' 5673',' 5343',' 5483',' 8149',' 8248',' 7281',' 5676',' 213',' 7207',' 7208',' 7211',' 7210',' 7209',' 214',' 215',' 5327',' 1772',' 2563',' 2160',' 1675',' 1807',' 2963',' 1578',' 209',' 2745',' 2562',' 5834',' 2306',' 5484',' 5878',' 7235',' 7237',' 2396',' 7236',' 5949',' 206',' 3414',' 3598',' 3191',' 3439',' 3683',' 3724',' 3888',' 3958',' 4003',' 3253',' 5564',' 3379',' 3852',' 2292',' 5441',' 5330',' 5329',' 167',' 5942',' 5422',' 5623',' 5624',' 5625',' 5626',' 1786',' 168',' 3913',' 169',' 5443',' 5446',' 6985',' 6984',' 193',' 5114',' 6238',' 170',' 171',' 8451',' 2477',' 4057',' 1948',' 6183',' 502988',' 5915',' 1662',' 1483',' 5914',' 7305',' 7307',' 7306',' 181',' 7133',' 5207',' 173',' 2020',' 7054',' 1922',' 5939',' 5941',' 6268',' 502987',' 7230',' 176',' 4179',' 499972',' 177',' 178',' 179',' 180',' 5390',' 5687',' 5685',' 1893',' 184',' 5192',' 7304',' 8017',' 5907',' 8200',' 5426',' 500118',' 500008',' 8018',' 5387',' 5193',' 5194',' 6552',' 6460',' 175',' 6277',' 5841',' 6551',' 6170',' 6169',' 3032',' 2668',' 188',' 189',' 190',' 191',' 197',' 192',' 194',' 6463',' 196',' 200',' 5122',' 5123',' 7471',' 6870',' 201',' 1933',' 5567',' 7078',' 5385',' 1856',' 2427',' 187'))) {
          $line['g:age_group'] = 'adult';
          $line['g:gender'] = 'unisex';
          $line['g:size'] = 'one size';
          $line['g:color'] = 'unique color';
          
          if (!empty($config['option_size']) && !empty($item['product_option'])) {
            $sizes = array();
            
            foreach ($item['product_option'] as $option) {
              if ($option['id'] == $config['option_size']) {
                $sizes[] = $option['value'];
              }
            }
            
            if (!empty($sizes)) {
              $line['g:size'] = implode('/', $sizes);
            }
          }
          
          if (!empty($config['option_color']) && !empty($item['product_option'])) {
            $sizes = array();
            
            foreach ($item['product_option'] as $option) {
              if ($option['id'] == $config['option_color']) {
                $sizes[] = $option['value'];
              }
            }
            
            if (!empty($sizes)) {
              $line['g:color'] = implode('/', $sizes);
            }
          }
        }
      }
      
      if (!empty($config['store_category']) && !empty($item['category'])) {
        // $line['g:product_type'] = $item['category'];
        $line['g:product_type'] = str_replace('>',' > ',$item['product_category']);
      }
      
      if (!empty($item['coupon'])) {
        $line['g:promotion_id'] = $item['coupon'];
      }
      
      $output = "\t".'<item>'."\n";
      
      foreach ($line as $k => $v) {
        if (strpos($v, '<') !== false || strpos($v, '&') !== false || strpos($v, 'http') !== false) {
          $output .= "\t\t".'<'.$k.'><![CDATA['.html_entity_decode($v, ENT_QUOTES, 'UTF-8').']]></'.$k.'>'."\n";
        } else if ($v !== '') {
          $output .= "\t\t".'<'.$k.'>'.html_entity_decode($v, ENT_QUOTES, 'UTF-8').'</'.$k.'>'."\n";
        } else {
          $output .= "\t\t".'<'.$k.'/>'."\n";
        }
      }
      
      $images = $this->model_tool_universal_feed->getProductImages($item['product_id']);
      
      // add main image in additional because it takes the 1st one as default
      //$output .= "\t\t".'<g:additional_image_link><![CDATA[' . $image . ']]></g:additional_image_link>'."\n";
      
      foreach ($images as $i => $image) {
        if (true) {
          $output .= "\t\t".'<g:additional_image_link><![CDATA[' . HTTP_SERVER . 'image/' . $image['image'] . ']]></g:additional_image_link>'."\n";
        } else {
          $output .= "\t\t".'<g:additional_image_link><![CDATA[' . @$this->model_tool_image->resize($image['image'], 1000, 1000) . ']]></g:additional_image_link>'."\n";
        }
        if ($i >= 9) break; // limit is to 10 images
      }
      
      if (!empty($config['shipping'])) {
        foreach ($config['shipping'] as $shipping) {
          $shipping_data = explode(':', $shipping);
          
          if (count($shipping_data) == 5) {
            
            $weightLimits = array_shift($shipping_data);
            
            if (strpos($weightLimits, '-') === false) {
              die('Error: Incorrect weight restriction format, must be formated like 0-500');
            }
            
            list($lowLimit, $highLimit) = explode('-', $weightLimits);
            
            if ($realWeight < $lowLimit || $realWeight > $highLimit) {
              continue;
            }
          }
          
          if (count($shipping_data) != 4) continue;
          
          $output .= "\t\t".'<g:shipping>';
            $output .= "\n\t\t\t".'<g:country>'.$shipping_data[0].'</g:country>';
            $output .= "\n\t\t\t".'<g:region>'.$shipping_data[1].'</g:region>';
            $output .= "\n\t\t\t".'<g:service>'.$shipping_data[2].'</g:service>';
            $output .= "\n\t\t\t".'<g:price>'.$shipping_data[3].'</g:price>';
          $output .= "\n\t\t".'</g:shipping>'."\n";
        }
      }
      
      $output .= "\t".'</item>'."\n";
      
      fwrite($fh, $output);
      
      $row++;
    }
    
    // return false when no more products
    return !empty($output);
  }
  
  public function getTotalItems($data = array()) {
    return $this->model_universal_feed_driver_product->getTotalItems($data);
  }
  
  private function getGoogleCategory($item_id) {
		$gcats = array();
		$categories = $this->db->query("SELECT c.google_merchant_id, cd.name FROM " . DB_PREFIX . "product_to_category p2c LEFT JOIN " . DB_PREFIX . "category c ON (p2c.category_id = c.category_id) LEFT JOIN " . DB_PREFIX . "category_description cd ON (c.category_id = cd.category_id) AND cd.language_id = " . $this->config->get('config_language_id') . " WHERE product_id = '" . (int)$item_id . "'")->rows;
		
		foreach($categories as $category) {
      if (!empty($category['google_merchant_id'])) {
        return array(
          'id' => $category['google_merchant_id'],
          //'name' => $category['name'],
        );
      }
		}
	}
  
  private $gg_cats_array;
  
  private function getGoogleCategoryByName($item_id) {
    if (empty($this->gg_cats_array)) {
      $this->gg_cats_array = $this->getGoogleCategories(NULL, true, true);
    }
    
		$gcats = array();
		$categories = $this->db->query("SELECT c.google_merchant_id, cd.name FROM " . DB_PREFIX . "product_to_category p2c LEFT JOIN " . DB_PREFIX . "category c ON (p2c.category_id = c.category_id) LEFT JOIN " . DB_PREFIX . "category_description cd ON (c.category_id = cd.category_id) AND cd.language_id = " . $this->config->get('config_language_id') . " WHERE product_id = '" . (int)$item_id . "'")->rows;
		
		foreach($categories as $category) {
      if (!empty($category['google_merchant_id'])) {
        return array(
          'id' => $category['google_merchant_id'],
          'name' => isset($this->gg_cats_array[$category['google_merchant_id']]) ? $this->gg_cats_array[$category['google_merchant_id']] : '',
        );
      }
		}
	}
  
  public function getGoogleCategories($categories = null, $return = false, $nojson = false) {
    $gg_cats_file = 'admin/view/universal_feed/google_taxonomy/'.substr($this->config->get('config_admin_language'), 0, 2).'.txt';
    
    if (!file_exists($gg_cats_file)) {
      $gg_cats_file = 'admin/view/universal_feed/google_taxonomy/en.txt';
    }
    
    $gg_cats = array();
    $gg_cats_file = file($gg_cats_file);
    
    array_shift($gg_cats_file);
    
    foreach ($gg_cats_file as $gg_cat) {
      list($id, $fullname) = explode('-', $gg_cat, 2);
      $id = (int) $id;
      
      $gg_cats[$id] = trim($fullname);
      
      /*
      if (strrpos($fullname, '>') !== false) {
        $name = substr($fullname, strrpos($fullname, '>') + 1);
        $cats = substr($fullname, 0, strrpos($fullname, '>') -1);
      } else {
        $name = $fullname;
        $cats = '';
      }
      

      $gg_cats[] = array(
        'id' => $id,
        'name' => trim($name),
        'cats' => trim($cats),
      );
      */
    }
    
    return $gg_cats;
  }
}