Your IP : 216.73.216.84


Current Path : /home/h/e/l/helpink/www/administrator/components/com_jbusinessdirectory/models/
Upload File :
Current File : /home/h/e/l/helpink/www/administrator/components/com_jbusinessdirectory/models/offer.php

<?php
/**
 * @package    J-BusinessDirectory
 *
 * @author     CMSJunkie http://www.cmsjunkie.com/
 * @copyright  Copyright (C) 2007 - 2022 CMSJunkie. All rights reserved.
 * @license    https://www.gnu.org/licenses/agpl-3.0.en.html
 */
use Joomla\String\StringHelper;

defined('_JEXEC') or die('Restricted access');

jimport('joomla.application.component.modeladmin');
require_once(HELPERS_PATH.'/category_lib.php');
require_once BD_CLASSES_PATH.'/attributes/attributeservice.php';
use Joomla\Utilities\ArrayHelper;

/**
 * Offer model
 *
 */
class JBusinessDirectoryModelOffer extends JModelAdmin {
	/**
	 * @var		string	The prefix to use with controller messages.
	 * @since   1.6
	 */
	protected $text_prefix = 'COM_JBUSINESSDIRECTORY_OFFER';
	protected $tableHeader;
	protected $header = array();
	protected $headerDifferences = array();
	protected $failedOffers = array();
	protected $error_row = 0;
	protected $newOffersCount = 0 ;
	protected $categories;
	protected $countries;
	protected $languages;

	/**
	 * Model context string.
	 *
	 * @var		string
	 */
	protected $_context		= 'com_jbusinessdirectory.offer';

	/**
	 * JBusinessDirectoryModelOffer constructor.
	 * @param array $config
	 */
	public function __construct($config = array()) {
		$this->appSettings = JBusinessUtil::getApplicationSettings();

		parent::__construct($config);
	}

	/**
	 * Method to test whether a record can be deleted.
	 *
	 * @param   object	A record object.
	 *
	 * @return  boolean  True if allowed to delete the record. Defaults to the permission set in the component.
	 */
	protected function canDelete($record) {
		return true;
	}

	/**
	 * Method to test whether a record can be deleted.
	 *
	 * @param   object	A record object.
	 *
	 * @return  boolean  True if allowed to change the state of the record. Defaults to the permission set in the component.
	 */
	protected function canEditState($record) {
		return true;
	}

	/**
	 * Returns a Table object, always creating it
	 *
	 * @param   type	The table type to instantiate
	 * @param   string	A prefix for the table class name. Optional.
	 * @param   array  Configuration array for model. Optional.
	 * @return  JTable	A database object
	*/
	public function getTable($type = 'Offer', $prefix = 'JTable', $config = array()) {
		return JTable::getInstance($type, $prefix, $config);
	}

	/**
	 * Method to auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @since   1.6
	 */
	protected function populateState() {
		$app = JFactory::getApplication('administrator');

		// Load the User state.
		$id = JFactory::getApplication()->input->getInt('id');
		$this->setState('offer.id', $id);
		
		$type =JFactory::getApplication()->input->getInt('filter_type', OFFER_TYPE_OFFER);
		if (empty($type)) {
			if (!($type = $app->getUserState('com_jbusinessdirectory.offers.filter.type'))) {
				$type = JFactory::getApplication()->input->getInt('item_type');
			}
		}
		$this->setState('filter.type', $type);
	}

	/**
	 * Method to get a menu item.
	 *
	 * @param   integer	The id of the menu item to get.
	 *
	 * @return  mixed  Menu item data object on success, false on failure.
	 */
	public function &getItem($itemId = null) {
		$itemId = (!empty($itemId)) ? $itemId : (int) $this->getState('offer.id');
		$false	= false;

		$this->appSettings = JBusinessUtil::getApplicationSettings();

		// Get a menu item row instance.
		$table = $this->getTable();

		// Attempt to load the row.
		$return = $table->load($itemId);

		// Check for a table object error.
		if ($return === false && $table->getError()) {
			$this->setError($table->getError());
			return $false;
		}

		$properties = $table->getProperties(1);
		$value = Joomla\Utilities\ArrayHelper::toObject($properties, 'JObject');

		$companyTable = $this->getTable('Company');
		if (!empty($value->id) && !empty($value->companyId)) {
			$value->companyOptions = array($companyTable->getCompany($value->companyId));
		}
		
		$value->pictures = $this->getOfferPictures((int) $this->getState('offer.id'));
		
		if ($itemId == 0) {
			$value->startDate = date('Y-m-d');
			$value->endDate = date("Y-m-d");// current date
		}
		
		if (empty($value->currencyId)) {
			$value->currencyId = $this->appSettings->currency_id;
		}
		
		$value->startDate = JBusinessUtil::convertToFormat($value->startDate);
		$value->endDate = JBusinessUtil::convertToFormat($value->endDate);

		$typesTable = $this->getTable('OfferType');
		$value->types = $typesTable->getOfferTypes();
		
		$value->publish_start_date = JBusinessUtil::convertToFormat($value->publish_start_date);
		$value->publish_end_date = JBusinessUtil::convertToFormat($value->publish_end_date);

		if ($value->id == 0) {
			$value->time_zone = $this->appSettings->default_time_zone;
		}

		if ($value->publish_start_time != '00:00:00') {
			$value->publish_start_time = JBusinessUtil::convertTimeToFormat($value->publish_start_time);
		} else {
			$value->publish_start_time = null;
		}

		if ($value->publish_end_time != '00:00:00') {
			$value->publish_end_time = JBusinessUtil::convertTimeToFormat($value->publish_end_time);
		} else {
			$value->publish_end_time = null;
		}
		
		$companyCategoryTable = $this->getTable('CompanyCategory');
		$value->selectedCategories = $companyCategoryTable->getSelectedOfferCategories($itemId);
		if ($this->appSettings->enable_multilingual) {
			JBusinessDirectoryTranslations::updateCategoriesTranslation($value->selectedCategories);
		}

		$companyCategoryTable = $this->getTable('CompanyCategory');
		$value->selectedSubCategories = $companyCategoryTable->getSelectedOfferCategoriesList($itemId);

		foreach ($value->selectedSubCategories as $cat) {
			$cat->name = str_repeat('- ', $cat->level-1) . $cat->name;
		}

		
		$attributesTable = $this->getTable('OfferAttributes');
		$categoryId = null;
		if ($this->appSettings->enable_attribute_category) {
			$categoryId = -1;
			if (!empty($value->main_subcategory)) {
				$categoryId = $value->main_subcategory;
			}
		}
		$value->customFields = $attributesTable->getOfferAttributes($itemId, $categoryId);

		if (!empty($itemId)) {
			$value->stocks = $this->getOfferSellingAttributes($itemId, $value->main_subcategory);
		} else {
			$value->stocks = array();
		}

		if ($this->appSettings->enable_multilingual) {
			JBusinessDirectoryTranslations::updateAttributesTranslation($value->customFields);
		}

		$value->attachments = JBusinessDirectoryAttachments::getAttachments(OFFER_ATTACHMENTS, $itemId);

		$videosTable = $this->getTable('OfferVideos');
		$value->videos = $videosTable->getOfferVideos($itemId);

		$countriesTable = $this->getTable('Country');
		$value->countries = $countriesTable->getCountries();
		JBusinessDirectoryTranslations::updateCountriesTranslation($value->countries);

		$value->defaultAtrributes = JBusinessUtil::getAttributeConfiguration(DEFAULT_ATTRIBUTE_TYPE_OFFER);
		if (!empty($value->price)) {
			$value->price = JBusinessUtil::convertPriceFromMysql($value->price);
		}
		if (!empty($value->specialPrice)) {
			$value->specialPrice = JBusinessUtil::convertPriceFromMysql($value->specialPrice);
		}
		if (!empty($value->price_base)) {
			$value->price_base = JBusinessUtil::convertPriceFromMysql($value->price_base);
		}
		if (!empty($value->special_price_base)) {
			$value->special_price_base = JBusinessUtil::convertPriceFromMysql($value->special_price_base);
		}

		$regionTable = $this->getTable('Region');
		if(!empty($value->countryId)){
			$value->regions = $regionTable->getRegionsByCountry($value->countryId);
		} else {
			$value->regions = $regionTable->getRegions();
		}

		if(!empty($value->county)){
			$cityTable = $this->getTable('City');
			$value->cities = $cityTable->getCitiesByRegionName($value->county);
		}

		if ($value->item_type == OFFER_TYPE_PRODUCT) {
			$productMerchantsTable = $this->getTable('ProductMerchants');
			if (!empty($itemId)) {
				$value->selectedCompanies = $productMerchantsTable->getMerchantsByProduct($itemId);
			} else {
				$value->selectedCompanies = array();
			}

			if (!empty($value->selectedCompanies)) {
				$value->merchantsOptions = $productMerchantsTable->getMerchantsOptions($itemId);
			} else {
				$value->merchantsOptions = array();
			}
		}

		if(!empty($value->packages)){
			$value->selectedPackages = explode(',', (string)$value->packages);
		}

		//        if (!$this->appSettings->apply_attr_offers){
		//            foreach ($value->defaultAtrributes as &$config)
		//                $config = ATTRIBUTE_OPTIONAL ;
		//        }

		if (JBusinessUtil::isAppInstalled(JBD_APP_SELL_OFFERS)) {
			$user = JBusinessUtil::getUser();
			
			$shippingMethodsTable           = $this->getTable('ShippingMethod');
			$value->shippingMethods         = $shippingMethodsTable->getShippingMethods($user->id);
			if (empty($value->shippingMethods)) {
				$value->shippingMethods         = $shippingMethodsTable->getShippingMethods();
			}
			$value->selectedShippingMethods = $shippingMethodsTable->getOfferShippingMethods($itemId);
		}

		return $value;
	}

	/**
	 * Get the stocks for the item based on its main category which will be used to
	 * render the selling options on offer edit view
	 *
	 * @param $itemId int item ID
	 * @param $mainCategory int main category id
	 *
	 * @return array
	 *
	 * @since version
	 */
	public function getOfferSellingAttributes($itemId, $mainCategory){

		$categoryService = new JBusinessDirectorCategoryLib();
		$fullCategory = $categoryService->getCompleteCategoryById($mainCategory, CATEGORY_TYPE_OFFER);
		$stockTable = $this->getTable('OfferStock');
		$attributesTable = $this->getTable('OfferAttributes');

		//check if category is parent or subcategory. If its sub than add also category of level 1 to take the custom attributes
		if (empty($fullCategory) || $fullCategory['level'] == 1) {
			$stockCategory = $mainCategory;
		} else {
			if(!empty($fullCategory)){
				$stockCategory = $mainCategory;
			}
		}
		$stocks = $stockTable->getOfferStocks($itemId, $mainCategory);
		$stocksConfig = array();
		$newAttributes = array();
		$checkedOnce = false;
		//get offer attributes related with the stock category defined above and also the ones that do not have a category assigned
		$allOfferSellingAttributes = $attributesTable->getOfferAttributes($itemId, $stockCategory, true);

		if (!empty($stocks)) {
			foreach ($stocks as $key => $stock) {
				//get stock related selling attributes
				$stockAttributes = $stockTable->getOfferStocksConfig($itemId, $stock->id, $stockCategory);
				if (!$checkedOnce) {
					//check all attributes if any new one has been added and add it to the existing ones to display so the user can set the configurations
					foreach ($allOfferSellingAttributes as $allOfferSellingAttribute) {
						$found = false;
						foreach ($stockAttributes as $stockAttribute) {
							if ($stockAttribute->id == $allOfferSellingAttribute->id) {
								$found = true;
								break;
							}
						}
						if ($found == false) {
							$newAttributes[] = $allOfferSellingAttribute;
						}
					}
					// prevent the foreach to loop each time for every stock. One is enough
					$checkedOnce = true;
				}

				// if there are new attributes add them to each $stockAttributes so they can be found on each combinations
				if (!empty($newAttributes)) {
					foreach ($newAttributes as $attribute) {
						$attribute->attributeValue = '';
						$stockAttributes[] = $attribute;
					}
				}

				//order each selling attributes combination by ordering
				if (!empty($stockAttributes)) {
					usort($stockAttributes, fn($a, $b) => $a->ordering <=> $b->ordering);
				}

				//after every check is done add them to the final structure
				$stocksConfig[$stock->id] = $stockAttributes;
				$stocksConfig[$stock->id]['stock'] = $stock;
			}
		}

		//if no stock exists than just check if new attributes has been added and then create also an empty stock configuration to associate with it
		if (empty($stocksConfig)) {
			$sellingAttributes = $attributesTable->getOfferAttributes($itemId, $stockCategory, true);
			if (!empty($sellingAttributes)) {
				foreach ($sellingAttributes as &$att) {
					$att->attributeValue = '';
				}
				$stocksConfig[0] = $sellingAttributes;
				$newStock = new stdClass();
				$newStock->id = 0;
				$newStock->offer_id = $itemId;
				$newStock->qty = 0;
				$newStock->notify_stock_qty = 0;
				$stocksConfig[0]['stock'] = $newStock;
			}
		}

		return $stocksConfig;
	}
	
	public function getOfferPictures($offerId) {
		$query = "SELECT * FROM #__jbusinessdirectory_company_offer_pictures WHERE offerId =" . $offerId . " ORDER BY id ";

		$files = $this->_getList($query);
		$pictures = array();
		foreach ($files as $value) {
			$pictures[] = array(
				'id' => $value->id,
				'picture_title' => $value->picture_title,
				'picture_info' => $value->picture_info,
				'picture_path' => $value->picture_path,
				'picture_enable' => $value->picture_enable,
			);
		}

		return $pictures;
	}

	/**
	 * Saves the selected shipping methods for the offer
	 *
	 * @param $data array
	 *
	 * @return bool
	 *
	 * @since 5.1.0
	 */
	public function saveShippingMethods($data) {
		$shippingMethodIds  = isset($data["shippingMethodIds"])?$data["shippingMethodIds"]:array();
		$offerId     = (int) $this->getState('offer.id');
		$table       = $this->getTable("ShippingMethod");
		$table->deleteOfferShippingMethods($offerId);

		foreach ($shippingMethodIds as $i => $methodId) {
			if (!empty($methodId)) {
				$tableFields               = $this->getTable("OfferShippingMethod");
				$tableFields->offer_id = $offerId;
				$tableFields->shipping_method_id = $methodId;
				$tableFields->price = $data["shippingMethodPrices"][$i];

				if (!$tableFields->check()) {
					$application = JFactory::getApplication();
					$application->enqueueMessage($tableFields->getError(), 'error');
					return false;
				}
				if (!$tableFields->store()) {
					$application = JFactory::getApplication();
					$application->enqueueMessage($tableFields->getError(), 'error');
					return false;
				}
			}
		}

		return true;
	}

	/**
	 * Method to get the menu item form.
	 *
	 * @param   array  $data		Data for the form.
	 * @param   boolean	$loadData	True if the form is to load its own data (default case), false if not.
	 * @return  JForm	A JForm object on success, false on failure
	 * @since   1.6
	 */
	public function getForm($data = array(), $loadData = true) {
		
		// The folder and element vars are passed when saving the form.
		if (empty($data)) {
			$item		= $this->getItem();
			// The type should already be set.
		}
		// Get the form.
		$form = $this->loadForm('com_jbusinessdirectory.offer', 'item', array('control' => 'jform', 'load_data' => $loadData), true);
		if (empty($form)) {
			return false;
		}
		
		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed  The data for the form.
	 * @since   1.6
	 */
	protected function loadFormData() {
		// Check the session for previously entered form data.
		$data = JFactory::getApplication()->getUserState('com_jbusinessdirectory.edit.offer.data', array());

		if (empty($data)) {
			$data = $this->getItem();
		}

		return $data;
	}
	
	/**
	 * Check if the entered dates are valid
	 * @param unknown_type $data
	 */
	public function checkDates(&$data) {
		if (!empty($data["startDate"]) && !empty($data["endDate"])) {
			if (strtotime($data["startDate"]) > strtotime($data["endDate"])) {
				JFactory::getApplication()->enqueueMessage(JText::_('LNG_END_DATE_LOWER_THAN_START_DATE'), 'warning');
				$data["endDate"] = $data["startDate"];
			}
		}

		if (!empty($data["publish_start_date"]) && !empty($data["publish_end_date"])) {
			if (strtotime($data["publish_start_date"]) > strtotime($data["publish_end_date"])) {
				JFactory::getApplication()->enqueueMessage(JText::_('LNG_END_DATE_LOWER_THAN_START_DATE'), 'warning');
				$data["publish_end_date"] = $data["publish_start_date"];
			}
		}
	}
	
	/**
	 * Check for duplicate alias and generate a new alias
	 * @param unknown_type $busienssId
	 * @param unknown_type $alias
	 */
	public function checkAlias($busienssId, $alias) {
		$table = $this->getTable();
		while ($table->checkAlias($busienssId, $alias)) {
			$alias = StringHelper::increment($alias, 'dash');
		}
		return $alias;
	}
	
	/**
	 * Method to save the form data.
	 *
	 * @param   array  The form data.
	 * @return  boolean  True on success.
	 */
	public function save($data) {
		$id	= (!empty($data['id'])) ? $data['id'] : (int) $this->getState('offer.id');
		if (empty($data['id'])) {
			$data['id'] = 0;
		}
		$isNew = $id > 0? false:true;

		foreach ($data as &$item) {
			if (!is_array($item)) {
				$item = trim($item);
			}
		}

		JFactory::getApplication()->triggerEvent('onBeforeJBDSaveOffer', array($data, $isNew));
		
		if (!$this->appSettings->item_decouple && $data['item_type'] != OFFER_TYPE_PRODUCT) {
			if (!$this->checkPackageLimit($data["companyId"], $isNew, $id)) {
				JFactory::getApplication()->enqueueMessage(JText::_('LNG_PACKAGE_LIMIT_EXCEEDED'), 'warning');
				// reset company id
				$data["companyId"] = -1;
			}
		}else{
			if(empty($data["companyId"])){
				$data["companyId"] = -1;
			}
		}
		
		$controller = substr($data["task"], 0, strpos($data["task"], "."));
		if ($data["user_id"]!=0 && $controller == "managecompanyoffer") {
			if ($this->appSettings->enable_item_moderation == '0') {
				$data["approved"] = OFFER_APPROVED;
			} else {
				//if number of threshold is 0 then approve else check the number of approved items of this user
				if ($this->appSettings->enable_automated_moderation) {
					if ($this->appSettings->moderate_threshold == '0') {
						$data["approved"] = OFFER_APPROVED;
					} else {
						$table = $this->getTable();
						$totalApprovedUserItems = $table->getTotalUserOffers(array(), $data["user_id"], true);
						if ($totalApprovedUserItems >= $this->appSettings->moderate_threshold) {
							$data["approved"] = OFFER_APPROVED;
						}
					}
				}
			}
		}

		$this->checkDates($data);

		$data["startDate"] = JBusinessUtil::convertToMysqlFormat($data["startDate"], true);
		$data["endDate"] = JBusinessUtil::convertToMysqlFormat($data["endDate"], true);
		
		$data["publish_start_date"] = JBusinessUtil::convertToMysqlFormat($data["publish_start_date"], true);
		$data["publish_end_date"] = JBusinessUtil::convertToMysqlFormat($data["publish_end_date"], true);

		$data["publish_start_time"] = JBusinessUtil::convertTimeToMysqlFormat($data["publish_start_time"]);
		$data["publish_end_time"] = JBusinessUtil::convertTimeToMysqlFormat($data["publish_end_time"]);
	
		$data["price"] = JBusinessUtil::convertPriceToMysql($data["price"]);
		$data["specialPrice"] = JBusinessUtil::convertPriceToMysql($data["specialPrice"]);
		$data["price_base"] = JBusinessUtil::convertPriceToMysql($data["price_base"]);
		$data["special_price_base"] = JBusinessUtil::convertPriceToMysql($data["special_price_base"]);
	
		$data["total_coupons"] = intval($data["total_coupons"]);

		$defaultLng = JBusinessUtil::getLanguageTag();
		$description = 	JFactory::getApplication()->input->get('description_'.$defaultLng, '', 'RAW');
		$name = JFactory::getApplication()->input->get('subject_'.$defaultLng, '', 'RAW');
		$meta_title = JFactory::getApplication()->input->get('meta_title_'.$defaultLng, '', 'RAW');
		$meta_desc = JFactory::getApplication()->input->get('meta_description_'.$defaultLng, '', 'RAW');
		$meta_key = JFactory::getApplication()->input->get('meta_keywords_'.$defaultLng, '', 'RAW');

		if ((!empty($meta_key) && empty($data["meta_keywords"])) || !isset($data["meta_keywords"])) {
			$data["meta_keywords"] = $meta_key;
		}

		if ((!empty($meta_title) && empty($data["meta_title"])) || !isset($data["meta_title"])) {
			$data["meta_title"] = $meta_title;
		}

		if ((!empty($meta_desc) && empty($data["meta_description"])) || !isset($data["meta_description"])) {
			$data["meta_description"] = $meta_desc;
		}

		if (!empty($name) && empty($data["subject"])) {
			$data["subject"] = $name;
		}
		
		if (!empty($description) && empty($data["description"])) {
			$data["description"] = $description;
		}
		
		$shortDescription = JFactory::getApplication()->input->get('short_description_'.$defaultLng, '', 'RAW');
		if (empty($data["short_description"])) {
			$data["short_description"] = $shortDescription;
		}
		
		$additionalDescription = JFactory::getApplication()->input->get('additional_description_'.$defaultLng, '', 'RAW');
		if ((!empty($additionalDescription) && empty($data["price_text"])) || !isset($data["price_text"])) {
			$data["price_text"] = $additionalDescription;
		}
		
		$data["alias"]= JBusinessUtil::getAlias($data["subject"], $data["alias"]);
		$data["alias"] = $this->checkAlias($id, $data["alias"]);

		$data["description"] = JBusinessUtil::removeRelAttribute($data["description"]);

		if (empty($data["countryId"])) {
			$data["countryId"]= null;
		}
		
		if (empty($data["quantity"])) {
			$data["quantity"]= null;
		}

		if (empty($data["max_purchase"])) {
			$data["max_purchase"]= null;
		}
		
		if (empty($data["min_purchase"])) {
			$data["min_purchase"]= null;
		}

		if (empty($data['view_count'])) {
			$data['view_count'] = null;
		}

		if (empty($data["notify_offer_quantity"])) {
			$data["notify_offer_quantity"]= null;
		}	

		if (empty($data["review_score"])){
			$data["review_score"] = "0.0";
		}

		if(!empty($data['packages'])){
			$data['packages'] = implode(',', $data['packages']);
		}

		// Get a row instance.
		$table = $this->getTable();

		// Load the row if saving an existing item.
		if ($id > 0) {
			$table->load($id);
			$isNew = false;
		}

		// Bind the data.
		if (!$table->bind($data)) {
			$this->setError($table->getError());
			dump($table->getError());
			return false;
		}
		
		// Check the data.
		if (!$table->check()) {
			$this->setError($table->getError());
			dump($table->getError());
			return false;
		}

		// Store the data.
		if (!$table->store(true)) {
			$this->setError($table->getError());
			dump($table->getError());
			return false;
		}

		// dump($data);
		// dump($table);
		// exit;


		$id = $table->id;
		
		$properties = $table->getProperties(1);
		$offer = ArrayHelper::toObject($properties, 'JObject');

		$this->setState('offer.id', $table->id);
		$this->setState('managecompanyoffer.id', $table->id);

		if ($isNew && empty($data["no-email"])) {
			EmailService::sendNewOfferNotification($table, $data['item_type']);
		}

		if($isNew && $offer->state == 1) {
			NotificationService::sendBookmarkedCompanyItemsNotification($data["companyId"], $data["subject"], $id);
		}

		$imported = isset($data['imported'])?true:false;
		JBusinessDirectoryTranslations::saveTranslations(OFFER_DESCRIPTION_TRANSLATION, $table->id, 'description_', false, $imported, $data);
		JBusinessDirectoryTranslations::saveTranslations(OFFER_META_TRANSLATION, $table->id, '', true, $imported, $data);
		JBusinessDirectoryAttachments::saveAttachments(OFFER_ATTACHMENTS, OFFER_ATTACHMENTS_PATH, $table->id, $data, $id);

		if (JBusinessUtil::isAppInstalled(JBD_APP_SELL_OFFERS)) {
			$this->saveShippingMethods($data);
		}

		// if no category is selected, create a dummy relation with categoryId = -1 so that
		// the insertOfferRelations function deletes all other existing relations
		if (!isset($data['categories'])) {
			$data['categories'] = array(-1);
		}
		
		//save in companycategory table
		if (!empty($data["categories"])) {
			$table = $this->getTable('CompanyCategory');
			$table->insertOfferRelations($this->getState('offer.id'), $data["categories"]);
		}

		if ($data['item_type'] == OFFER_TYPE_PRODUCT) {
			//save merchants data
			$productMerchants = $this->getTable('ProductMerchants');
			$assListings = !empty($data["associated-listings"]) ? $data["associated-listings"] : null;
			$productMerchants->storeMerchants($this->getState('offer.id'), $assListings);
		}

		try {
			$this->storeAttributes($this->getState('offer.id'), $data);
			$this->storeSellingAttributes($this->getState('offer.id'), $data);

			$oldId = $isNew?0:$id;
			$this->storePictures($data, $this->getState('offer.id'), $oldId);

			$this->storeVideos($data, $this->getState('offer.id'));
		} catch (Exception $ex) {
			$this->setError($ex->getMessage());
		}
		
		// Clean the cache
		$this->cleanCache();
		
		
		//dispatch save offer
		JFactory::getApplication()->triggerEvent('onAfterJBDSaveOffer', array($offer, $isNew));
		
		return true;
	}

	public function storePictures($data, $offerId, $oldId) {
		$usedFiles = array();
		if (!empty($data['pictures'])) {
			foreach ($data['pictures'] as $value) {
				array_push($usedFiles, $value["picture_path"]);
			}
		}

		$pictures_path = JBusinessUtil::makePathFile(BD_PICTURES_UPLOAD_PATH);
		$offer_pictures_path = JBusinessUtil::makePathFile(OFFER_PICTURES_PATH.($offerId)."/");
		JBusinessUtil::removeUnusedFiles($usedFiles, $pictures_path, $offer_pictures_path);

		$picture_ids 	= array();
		foreach ($data['pictures'] as $value) {
			$row = $this->getTable('OfferPictures');
	
			//dbg($key);
			$pic 						= new stdClass();
			$pic->id		= 0;
			$pic->offerId 				= $offerId;
			$pic->picture_title	= $value['picture_title'];
			$pic->picture_info	= $value['picture_info'];
			$pic->picture_path	= $value['picture_path'];
			$pic->picture_enable	= $value['picture_enable'];
			//dbg($pic);

			$pic->picture_path = JBusinessUtil::moveFile($pic->picture_path, $offerId, $oldId, OFFER_PICTURES_PATH);

			//dbg($pic);
			//exit;
			if (!$row->bind($pic)) {
				throw( new Exception($row->getError()) );
				$this->setError($row->getError());
			}
			// Make sure the record is valid
			if (!$row->check()) {
				throw( new Exception($row->getError()) );
				$this->setError($row->getError());
			}
	
			// Store the web link table to the database
			if (!$row->store()) {
				throw( new Exception($row->getError()) );
				$this->setError($row->getError());
			}
	
			$picture_ids[] = $this->_db->insertid();
		}

		$query = " DELETE FROM #__jbusinessdirectory_company_offer_pictures
		WHERE offerId = '".$offerId."'
		".(count($picture_ids)> 0 ? " AND id NOT IN (".implode(',', $picture_ids).")" : "");
	
		// dbg($query);
		//exit;
		$this->_db->setQuery($query);
		try {
			$this->_db->execute();
		} catch (RuntimeException $e) {
			$this->setError($e->getMessage());
			return false;
		}
		//~prepare photos
	}

	public function getCurrencies() {
		$currenciesTable = JTable::getInstance("Currency", "JTable");
		$currencies = $currenciesTable->getCurrencies();
		return $currencies;
	}
	
	public function getCompanies() {
		$companiesTable = JTable::getInstance("Company", "JTable");
		$companies =  $companiesTable->getAllCompanies();
		return $companies;
	}
	
	public function deleteOffer($offerId) {
		$offersTable = $this->getTable("Offer");
		return $offersTable->delete($offerId);
	}
	
	public function changeState($id = null) {
		if (empty($id)) {
			$id = JFactory::getApplication()->input->getInt('id');
		}
		
		$offersTable = $this->getTable("Offer");
		$offer = $offersTable->getOffer($id);
		
		$appSettings = JBusinessUtil::getApplicationSettings();
		if ($appSettings->enable_packages && !$appSettings->item_decouple) {
			if (!$this->checkPackageLimit($offer->companyId, 1, $id) && ($offer->state == 0)) {
				JFactory::getApplication()->enqueueMessage(JText::_('LNG_PACKAGE_LIMIT_EXCEEDED'), 'warning');
				return false;
			}
		}
		
		return $offersTable->changeState($id);
	}
	
	public function changeStateOfferOfTheDay() {
		$this->populateState();
		$offersTable = $this->getTable("Offer");
		return $offersTable->changeStateOfferOfTheDay($this->getState('offer.id'));
	}
	
	public function changeStateFeatured($id) {
		$this->populateState();
		$offersTable = $this->getTable("Offer");
		return $offersTable->changeStateFeatured($id);
	}
	
	public function changeAprovalState($state) {
		$this->populateState();
		$offersTable = $this->getTable("Offer");
		$offer = $offersTable->getOffer($this->getState('offer.id'));
		
		$companiesTable = JTable::getInstance("Company", "JTable");
		$company = $companiesTable->getCompany($offer->companyId);
		
		$appSettings = JBusinessUtil::getApplicationSettings();
		if ($appSettings->enable_packages && !$appSettings->item_decouple) {
			if (!$this->checkPackageLimit($offer->companyId, 0, $this->getState('offer.id')) && ($offer->approved == 0 || $offer->approved == -1)) {
				JFactory::getApplication()->enqueueMessage(JText::_('LNG_PACKAGE_LIMIT_EXCEEDED'), 'warning');
				return false;
			}
		}
		
		if ($offer->approved==0 and $state==1) {
			EmailService::sendApproveOfferNotification($offer, $company);
		}
		
		return $offersTable->changeAprovalState($this->getState('offer.id'), $state);
	}

	/**
	 * Store offer custom attributes
	 *
	 * @param unknown $offerId
	 * @param unknown $data
	 */
	public function storeAttributes($offerId, $data) {
		#delete all ad attributes
		$attrTable =$this->getTable('OfferAttributes');
		$attrIds=array();
		foreach ($data as $key => $value) {
			#save ad attributes
			if (strpos($key, "attribute")===0) {
				$attributeArr = explode("_", $key);
				if (!empty($attributeArr[1])) {
					$attrIds[]=$attributeArr[1];
				}
			}
			if (strpos($key, "delete_attribute")===0) {
				$attributeArr = explode("_", $key);
				if (!empty($attributeArr[2])) {
					$attrIds[]=$attributeArr[2];
				}
			}
		}
		//$attrIds = array_unique($attrIds);
		
		if (!empty($attrIds) && !$attrTable->deleteOfferAttributes($offerId, $attrIds)) {
			$this->setError(JText::_("LNG_ERROR_DELETING_AD_ATTRIBUTES"));
		}
		
		foreach ($data as $key => $value) {
			#save ad attributes
			if (strpos($key, "attribute")===0) {
				$attributeArr = explode("_", $key);
				
				$offerAttributeTable =$this->getTable('OfferAttributes');
				$offerAttributeTable->offer_id= $offerId;
				if(is_int($value)){
					$offerAttributeTable->option_id= $value;
				}
				$offerAttributeTable->value= $value;
				$offerAttributeTable->attribute_id= $attributeArr[1];
				
				if (is_array($offerAttributeTable->value)) {
					$offerAttributeTable->value = implode(",", $offerAttributeTable->value);
				}
				
				$properties = $offerAttributeTable->getProperties(1);
				$value = Joomla\Utilities\ArrayHelper::toObject($properties, 'JObject');
				
				if (!$offerAttributeTable->store()) {
					$this->setError(JText::_("LNG_ERROR_SAVING_AD_ATTRIBUTES").$offerAttributeTable->getError());
				}
			}
		}
	}
	
	/**
	 * @param $offerId int offer id to which the combinations of quantity will be saved
	 * @param $data array contains the selling options combinations
	 *
	 * @return bool
	 *
	 * @since version
	 */
	public function storeSellingAttributes($offerId, $data){
		$stockTable =$this->getTable('OfferStock');
		$actualStock = $stockTable->getOfferStocks($offerId);
		$stockIds = array();
		if (!empty($actualStock)) {
			foreach ($actualStock as $stock) {
				$stockIds[] = $stock->id;
			}
		}

		//delete previous stock configurations
		if (!empty($stockIds)) {
			$stockConfigTable = $this->getTable('OfferStockConfig');
			$stockConfigTable->deleteConfigurationsByStockId(implode(',', $stockIds));
		}
		$stockTable->deleteStockByOfferId($offerId);

		$stockQuantities    = isset($data["quantities"])?$data["quantities"]:array();
		$stockNotifySales   = isset($data["notify_stock_qty"])?$data["notify_stock_qty"]:array();
		$stockPrices = isset($data["stock_price"])?$data["stock_price"]:array();
		
		$attrIds=array();
		foreach ($data as $key => $value) {
			#save ad attributes
			if (strpos($key, "selling-attribute") === 0) {
				$attributeArr = explode("_", $key);
				if (!empty($attributeArr[1])) {
					$attrIds[] = $attributeArr[1];
				}
			}
		}
		$attrIds = array_unique($attrIds);

		//store item stocks
		if (!empty($stockQuantities)) {
			foreach ($stockQuantities as $key => $quantity) {
				$stockTable =$this->getTable('OfferStock');
				$stockTable->offer_id           = $offerId;
				$stockTable->qty                = $stockQuantities[$key];
				$stockTable->notify_stock_qty   = $stockNotifySales[$key];
				$stockTable->price			    = !empty($stockPrices[$key]) ? $stockPrices[$key] : 0;
				$stockTable->stock_main_category = $data['main_subcategory'];

				if (!$stockTable->store()) {
					$this->setError(JText::_("LNG_ERROR_SAVING_STOCK") . $stockTable->getError());
				}
				$stockId = $stockTable->id;
				//store stocks configurations
				foreach ($attrIds as $attrId) {
					$stockConfigTable = $this->getTable('OfferStockConfig');
					$stockConfigTable->id = 0;
					$stockConfigTable->stock_id = $stockId;
					$stockConfigTable->attribute_id = $attrId;
					$stockConfigTable->attribute_value = $data['selling-attribute_'.$attrId][$key];

					if (!$stockConfigTable->store()) {
						$this->setError(JText::_("LNG_ERROR_SAVING_STOCK_CONFIGURATION") ." ". $stockConfigTable->getError());
					}
				}
			}
		}
		return true;
	}

	public function getStates() {
		$states = array();
		$state = new stdClass();
		$state->value = 0;
		$state->text = JTEXT::_("LNG_INACTIVE");
		$states[] = $state;
		$state = new stdClass();
		$state->value = 1;
		$state->text = JTEXT::_("LNG_ACTIVE");
		$states[] = $state;
	
		return $states;
	}
	
	public function getStatuses() {
		$statuses = array();
		$status = new stdClass();
		$status->value = 0;
		$status->text = JTEXT::_("LNG_NEEDS_CREATION_APPROVAL");
		$statuses[] = $status;
		$status = new stdClass();
		$status->value = 1;
		$status->text = JTEXT::_("LNG_DISAPPROVED");
		$statuses[] = $status;
		$status = new stdClass();
		$status->value = 2;
		$status->text = JTEXT::_("LNG_APPROVED");
		$statuses[] = $status;
	
		return $statuses;
	}

	/**
	 * Method to delete groups.
	 *
	 * @param   array  An array of item ids.
	 * @return  boolean  Returns true on success, false on failure.
	 */
	public function delete(&$itemIds) {
		// Sanitize the ids.
		$itemIds = (array) $itemIds;
		Joomla\Utilities\ArrayHelper::toInteger($itemIds);
	
		// Get a group row instance.
		$table = $this->getTable();
	
		// Iterate the items to delete each one.
		foreach ($itemIds as $itemId) {
			if (!$table->delete($itemId)) {
				$this->setError($table->getError());
				return false;
			}
			
			if (!$this->deleteFiles($itemId)) {
				$this->setError("Could not delete files");
				return false;
			}

			if (!$table->deleteAllDependencies($itemId)) {
				$this->setError($table->getError());
				return false;
			}

			JBusinessDirectoryTranslations::deleteTranslationsForObject(OFFER_DESCRIPTION_TRANSLATION, $itemId);
		}
	
		// Clean the cache
		$this->cleanCache();
	
		return true;
	}
	
	/**
	 * Delete offer files
	 * @param $itemId
	 * @return boolean
	 */
	public function deleteFiles($itemId) {
		$imagesDir = BD_PICTURES_UPLOAD_PATH .OFFER_PICTURES_PATH.($itemId);
		JBusinessUtil::removeDirectory($imagesDir);
		
		$attachmentDir = BD_ATTACHMENT_UPLOAD_PATH .OFFER_ATTACHMENTS_PATH.$itemId;
		JBusinessUtil::removeDirectory($attachmentDir);
		
		return true;
	}

	/**
	 * Method to perform batch operations on an item or a set of items.
	 *
	 * @param   array  $commands  An array of commands to perform.
	 * @param   array  $pks       An array of item ids.
	 * @param   array  $contexts  An array of item contexts.
	 *
	 * @return  boolean  Returns true on success, false on failure.
	 *
	 * @since   12.2
	 */
	public function batch($vars, $pks, $contexts) {
		// Sanitize ids.
		$pks = array_unique($pks);
		Joomla\Utilities\ArrayHelper::toInteger($pks);

		// Remove any values of zero.
		if (array_search(0, $pks, true)) {
			unset($pks[array_search(0, $pks, true)]);
		}

		if (empty($pks)) {
			$this->setError(JText::_('JGLOBAL_NO_ITEM_SELECTED'));

			return false;
		}

		$done = false;

		// Set some needed variables.
		$this->user = JBusinessUtil::getUser();
		$this->table = $this->getTable();
		$this->tableClassName = get_class($this->table);
		$this->batchSet = true;
		// Parent exists so let's proceed
		while (!empty($pks)) {
			// Pop the first ID off the stack
			$pk = array_shift($pks);

			$this->table->reset();

			// Check that the row actually exists
			if (!$this->table->load($pk)) {
				if ($error = $this->table->getError()) {
					// Fatal error
					$this->setError($error);

					return false;
				} else {
					// Not fatal error
					$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk));
					continue;
				}
			}

			// set new approval state
			if ($vars["approval_status_id"]!="") {
				$this->table->approved = $vars["approval_status_id"];
			}

			// set new approval state
			if ($vars["featured_status_id"]!="") {
				$this->table->featured = $vars["featured_status_id"];
			}

			// set new approval state
			if ($vars["state_id"]!="") {
				$this->table->state = $vars["state_id"];
			}

			// Check the row.
			if (!$this->table->check()) {
				$this->setError($this->table->getError());

				return false;
			}

			// Store the row.
			if (!$this->table->store()) {
				$this->setError($this->table->getError());

				return false;
			}
		}

		// Clean the cache
		$this->cleanCache();

		return true;
	}

	public function getImportStatus() {
		$result = new stdClass();
		$result->differences = $this->headerDifferences;
		$result->correctHeader = $this->tableHeader;
		$result->failedOffers = $this->failedOffers;
		$result->newOffers = $this->newOffersCount;

		if ($result->differences) {
			$msg = JText::_('LNG_NOT_RECOGNIZED_HEADERS')."<br />".implode(", ", $result->differences);
			JFactory::getApplication()->enqueueMessage($msg, 'warning');
			$msg = JText::_('LNG_ALLOWED_HEADER')."<br />".implode(", ", $result->correctHeader);
			$msg .= "<br /><br />";
			JFactory::getApplication()->enqueueMessage($msg, 'success');
		}

		if ($result->failedOffers) {
			$message = JText::_('LNG_IMPORT_FAILED_FOR');
			JFactory::getApplication()->enqueueMessage(JText::_('LNG_IMPORT_FAILED_FOR'), 'warning');
			foreach ($result->failedOffers as $item) {
				$message = $message.JFactory::getApplication()->enqueueMessage(JText::_('LNG_ROW') . " " . $item->row . "  " . JText::_('LNG_OFFER_NAME') . " " . $item->name, 'warning');
			}
		}

		if ($result->newOffers) {
			$message = JText::plural('COM_JBUSINESS_DIRECTORY_N_OFFERS_IMPORTED', $result->newOffers);
			JFactory::getApplication()->enqueueMessage($message, 'success');
		}

		return $result;
	}

	/**
	 * Get the categories and languages before the import starts
	 */
	public function initializeImport() {
		$this->categories = $this->getCategories();
		$this->countries = $this->getCountries();
		$this->languages = JBusinessUtil::getLanguages();
	}

	/**
	 * Import an offer based on provided data
	 * @param array $offer
	 */
	public function importOffers($offer) {
		$updateExisting = JFactory::getApplication()->input->get("update_existing");
		$categoryIds = array();
		$subCategoryId = "";
		$datas = array();
		if (!empty($offer["subject"])) {
			if (!empty($offer["categories"])) {
				$categoriesNames = explode(",", $offer["categories"]);
				foreach ($categoriesNames as $category) {
					if (empty($category)) {
						continue;
					}

					//dump("search ".$category);
					$cat = $this->getCategoryByName($this->categories, $category);
					//	dump($cat[0]->name);
					if (!isset($cat)) {
						continue;
					}
					$categoryIds[] = $cat[0]->id;

					if (!empty($offer["main_subcategory"]) && $offer["main_subcategory"] == $category) {
						$subCategoryId = $cat[0]->id;
					}
				}
				$datas["categories"] = $categoryIds;
				$datas["main_subcategory"] = $subCategoryId;
			}			

			$countryId = 0;
			if (isset($offer["country"])) {
				if (isset($this->countries[$offer["country"]])) {
					$countryId = $this->countries[$offer["country"]]->id;
				}
			}
			
			$datas["id"] = isset($offer["id"]) ? $offer["id"] : "";			
			if (isset($updateExisting)) {
				$offersTable = $this->getTable("Offer");
				$existingOffer = $offersTable->getOfferByName($offer["name"]);
				$datas["id"] = $existingOffer->id;
			}
			$datas["subject"] = isset($offer["subject"]) ? $offer["subject"] : "";
			$datas["alias"] = JBusinessUtil::getAlias($offer["name"], $offer["alias"]);
			$datas["companyId"] = isset($offer["company_id"]) ? $offer["company_id"] : "";
			$datas["currencyId"] = isset($offer["currency_id"]) ? $offer["currency_id"] : "";
			$datas["price"] = isset($offer["price"]) ? $offer["price"] : "";
			$datas["specialPrice"] = isset($offer["special_price"]) ? $offer["special_price"] : "";
			$datas["price_base"] = isset($offer["price_base"]) ? $offer["price_base"] : "";
			$datas["price_base_unit"] = isset($offer["price_base_unit"]) ? $offer["price_base_unit"] : "";
			$datas["special_price_base"] = isset($offer["special_price_base"]) ? $offer["special_price_base"] : "";
			$datas["special_price_base_unit"] = isset($offer["special_price_base_unit"]) ? $offer["special_price_base_unit"] : "";
			$datas["total_coupons"] = isset($offer["total_coupons"]) ? $offer["total_coupons"] : "";
			$datas["startDate"] = isset($offer["start_date"]) ? $offer["start_date"] : "";
			$datas["endDate"] = isset($offer["end_date"]) ? $offer["end_date"] : "";
			$datas["offerOfTheDay"] = isset($offer["offer_of_the_day"]) ? $offer["offer_of_the_day"] : "";
			$datas["view_type"] = isset($offer["view_type"]) ? $offer["view_type"] : "";
			$datas["url"] = isset($offer["url"]) ? $offer["url"] : "";
			$datas["article_id"] = isset($offer["article_id"]) ? $offer["article_id"] : "";
			$datas["featured"] = isset($offer["featured"]) ? $offer["featured"] : "";

			if(!empty($offer["created"])){
				$datas["created"] =  $offer["created"];
			}

			$datas["show_time"] = isset($offer["show_time"]) ? $offer["show_time"] : "";
			$datas["publish_start_time"] = isset($offer["publish_start_time"]) ? $offer["publish_start_time"] : "";
			$datas["publish_end_time"] = isset($offer["publish_end_time"]) ? $offer["publish_end_time"] : "";
			$datas["expiration_email_date"] = isset($offer["expiration_email_date"]) ? $offer["expiration_email_date"] : "";
			$datas["enable_offer_selling"] = isset($offer["enable_offer_selling"]) ? $offer["enable_offer_selling"] : "";
			$datas["min_purchase"] = isset($offer["min_purchase"]) ? $offer["min_purchase"] : "";
			$datas["max_purchase"] = isset($offer["max_purchase"]) ? $offer["max_purchase"] : "";
			$datas["quantity"] = isset($offer["quantity"]) ? $offer["quantity"] : "";
			$datas["description"] = isset($offer["description"]) ? $offer["description"] : "";
			$datas["short_description"] = isset($offer["short_description"]) ? $offer["short_description"] : "";
			$datas["address"] = isset($offer["address"]) ? $offer["address"] : "";
			$datas["city"] = isset($offer["city"]) ? $offer["city"] : "";
			$datas["county"] = isset($offer["county"]) ? $offer["county"] : "";
			$datas["publish_start_date"] = isset($offer["publish_start_date"]) ? $offer["publish_start_date"] : null;
			$datas["publish_end_date"] = isset($offer["publish_end_date"]) ? $offer["publish_end_date"] : null;
			$datas["latitude"] = isset($offer["latitude"]) ? $offer["latitude"] : "";
			$datas["longitude"] = isset($offer["longitude"]) ? $offer["longitude"] : "";
			$datas["viewCount"] = isset($offer["view_count"]) ? $offer["view_count"] : "";
			$datas["picture"] = isset($offer["picture"]) ? $offer["picture"] : "";
			$datas["meta_title"] = isset($offer["meta_title"]) ? $offer["meta_title"] : "";
			$datas["meta_description"] = isset($offer["meta_description"]) ? $offer["meta_description"] : "";
			$datas["meta_keywords"] = isset($offer["meta_keywords"]) ? $offer["meta_keywords"] : "";
			$datas["province"] = isset($offer["province"]) ? $offer["province"] : "";
			$datas["area"] = isset($offer["area"]) ? $offer["area"] : "";
			$datas["no-email"] = 1;
			$datas["countryId"] = $countryId;
			$datas["postalCode"] = isset($offer["postal_code"]) ? $offer["postal_code"] : "";
			$datas["street_number"] = isset($offer["street_number"]) ? $offer["street_number"] : "";
			$datas["item_type"] = isset($offer["item_type"]) ? $offer["item_type"] : "";

			foreach ($this->languages as $lng) {
				$datas["subject_".strtolower($lng)] = isset($offer["subject_".strtolower($lng)]) ? $offer["subject_".strtolower($lng)] : "";
				$datas["short_description_".strtolower($lng)] = isset($offer["short_description_".strtolower($lng)]) ? $offer["short_description_".strtolower($lng)] : "";
				$datas["description_".strtolower($lng)] = isset($offer["description_".strtolower($lng)]) ? $offer["description_".strtolower($lng)] : "";
				$datas["meta_title_".strtolower($lng)] = isset($offer["meta_title_".strtolower($lng)]) ? $offer["meta_title_".strtolower($lng)] : "";
				$datas["meta_description_".strtolower($lng)] = isset($offer["meta_description_".strtolower($lng)]) ? $offer["meta_description_".strtolower($lng)] : "";
				$datas["meta_keywords_".strtolower($lng)] = isset($offer["meta_keywords_".strtolower($lng)]) ? $offer["meta_keywords_".strtolower($lng)] : "";
			}
			$datas["imported"] = true;

			if (!empty($datas["picture"])) {
				$datas["picture"] = explode(",", $datas["picture"]);
				$pictures = [];
				foreach ($datas["picture"] as $key => $picture) {
					$picturesData = explode('#', $picture);

					$picTmp = [];
					$picTmp['picture_title'] = $picturesData[1];
					$picTmp['picture_info'] = $picturesData[2];
					$picTmp['picture_path'] = $picturesData[0];
					$picTmp['picture_enable'] = 1;

					$pictures[] = $picTmp;
				}
				$datas['pictures'] = $pictures;
				$datas['images_included'] = 1;
			}

			$datas["state"] = isset($offer["state"]) ? $offer["state"] : 1;
			$datas["approved"] = isset($offer["approved"]) ? $offer["approved"] : 1;

			//load custom attributes
			$attributesTable = JTable::getInstance("Attribute", "JTable");
			$attributes = $attributesTable->getAttributesWithTypes();

			$attributesTable = JTable::getInstance("AttributeOptions", "JTable");
			$attributeOptions = $attributesTable->getAllAttributesWithOptions();
			$appSettings = JBusinessUtil::getApplicationSettings();
			foreach ($attributes as $attribute) {
				$attribute->name = 'attribute_'.strtolower($attribute->name);

				if (!empty($offer[$attribute->name])) {
					$attrValues = $offer[$attribute->name];
					$attrValues = explode(",", $attrValues);
					foreach ($attrValues as $value) {
						if ($attribute->attr_type == "input" || $attribute->attr_type == "textarea" || $attribute->attr_type == "link") {
							$datas["attribute_" . $attribute->id][] = $offer[$attribute->name];
							break;
						} else {
							foreach ($attributeOptions as $attributeOption) {
								if ($appSettings->enable_multilingual) {
									$attributeOption->name = JBusinessDirectoryTranslations::getTranslatedItemName($attributeOption->name);
								}
								if ($attributeOption->attr_id == $attribute->id && $attributeOption->name == $value) {
									$datas["attribute_" . $attribute->id][] = $attributeOption->id;
								}
							}
						}
					}
				}
			}

			try {
				$this->setState('offer.id', 0);
				$this->error_row++;
				if ($this->save($datas)) {
					$this->newOffersCount++;
				} else {
					//dump("cannot save offer");
					$failedOffer = new stdClass();
					$failedOffer->name = $datas["subject"];
					$failedOffer->row = $this->error_row;
					array_push($this->failedOffers, $failedOffer);
				}
			} catch (Exception $e) {
				dump($e);
			}
		} else {
			$failedOffer = new stdClass();
			$this->error_row++;
			$failedOffer->name = JText::_('LNG_UNKNOWN');
			
			$failedOffer->row = $this->error_row;
			array_push($this->failedOffers, $failedOffer);
		}

	}

	public function getCountries() {
		$result = array();
		$countriesTable = $this->getTable("Country");
		$countries = $countriesTable->getCountries();
		foreach ($countries as $country) {
			$result[$country->country_name] = $country;
		}

		return $result;
	}

	public function getCategories() {
		$categoryService = new JBusinessDirectorCategoryLib();
		$categoryTable = $this->getTable("Category", "JBusinessTable");
		$categories = $categoryTable->getAllCategories(CATEGORY_TYPE_OFFER);
		$categories = $categoryService->processCategoriesByName($categories);
		return $categories;
	}


	public function getCategoryByName($categories, $categoryName) {
		$categoryService = new JBusinessDirectorCategoryLib();
		$cat = null;
		$category = $categoryService->findCategoryByName($categories, $cat, $categoryName);

		return $category;
	}

	/**
	 * Check if headers on the file that will be imported are OK
	 * @return bool
	 */
	public function checkHeaders() {
		$attributesTable = JTable::getInstance("Attribute", "JTable");
		$attributes = $attributesTable->getAttributes();

		$this->tableHeader = array("id","subject", "alias", "company_id", "currency_id", "short_description", "description",
				"CategoriesIds", "categories", "picture", "price", "special_price", "price_base", "price_base_unit",
				"special_price_base", "special_price_base_unit", "total_coupons", "start_date", "end_date", "state",
				"approved", "offer_of_the_day", "view_count", "address", "city", "county", "publish_start_date",
				"publish_end_date", "view_type", "url", "article_id", "latitude", "longitude", "featured", "created", "item_type",
				"show_time", "publish_start_time", "publish_end_time", "expiration_email_date", "main_category_id", "main_subcategory",
				"enable_offer_selling", "min_purchase", "max_purchase", "postal_code","country","street_number", "quantity", "meta_title", "meta_description",
				"meta_keywords", "province", "area");

		if (!empty($attributes)) {
			foreach ($attributes as $attribute) {
				array_push($this->tableHeader, 'attribute_'.$attribute->name);
			}
		}

		foreach ($this->languages as $lng) {
			array_push($this->tableHeader, "subject_$lng");
			array_push($this->tableHeader, "short_description_$lng");
			array_push($this->tableHeader, "description_$lng");
			array_push($this->tableHeader, "meta_title_$lng");
			array_push($this->tableHeader, "meta_description_$lng");
			array_push($this->tableHeader, "meta_keywords_$lng");
		}

		$headerDifferences = array_diff($this->header, $this->tableHeader);
		if ($headerDifferences != null) {
			$this->headerDifferences = $headerDifferences;
			return false;
		}
		return true;
	}

	/**
	 * Prepare the file content to be imported
	 * @param string $filePath
	 * @param string $delimiter
	 */
	public function importOffersFromCSV($filePath, $delimiter) {
		$row = 1;
		$this->initializeImport();
		
		if (($handle = fopen($filePath, "r")) !== false) {
			while (($data = fgetcsv($handle, 9000, $delimiter)) !== false) {
				$offerData = array();

				if ($row == 1) {
					$this->header = $data;
					$this->checkHeaders();
					$row ++;
					continue;
				}
				$num = count($data);

				//echo "<p> $num fields in line $row: <br /></p>\n";
				$row++;
				for ($c = 0; $c < $num; $c++) {
					$offerData[strtolower($this->header[$c])] = $data[$c];
				}

				$this->importOffers($offerData);

				if (in_array("id", $this->header)){
					JFactory::getApplication()->enqueueMessage(JText::_('LNG_ID_COLUMN_DETECTED_WARNING'), 'warning');
				}
			}
		}
	}

	/**
	 * Prepare the file content to imported
	 * @param array $csvContent
	 * @param string $delimiter
	 */
	public function importOffersFromTextArea($csvContent, $delimiter) {
		$row = 1;
		$this->initializeImport();
		foreach ($csvContent as $key => $content) {
			$data = str_getcsv($content, $delimiter);

			if ($row == 1) {
				$this->header = $data;
				$this->checkHeaders();
				$row ++;
				continue;
			}

			$num = count($data);
			for ($c = 0; $c < $num; $c++) {
				$offerData[strtolower($this->header[$c])] = $data[$c];
			}

			$this->importOffers($offerData);
			$row++;
		}
	}

	/**
	 * Method to check if actual number of offers belonging to
	 * a company has exceeded it's package limits
	 *
	 * @param $companyId int ID of the company
	 * @param $isNew boolean Company if is new of exists
	 * @param $id int Id of the offer
	 * @return bool true if it does not exceed, false otherwise
	 */
	public function checkPackageLimit($companyId, $isNew, $id) {
		if (empty($companyId)) {
			return false;
		}

		$maxOffers = $this->appSettings->max_offers;
		$offerCountType = 1;
		if ($this->appSettings->enable_packages) {
			$packagesTable = $this->getTable('Package', 'JTable');
			$package = $packagesTable->getCompanyPackage($companyId);

			if (empty($package)) {
				return false;
			}

			$maxOffers = $package->max_offers;
			$offerCountType = $package->offer_count_type;
		}
		

		$offerTable = $this->getTable();
		$nrOffers = (int)$offerTable->getTotalOffersByCompany($companyId, $offerCountType);
		
		$increment = $isNew?1:0;
		$offer = $offerTable->getOffer($id);
		if ($maxOffers != 0) {
			if (($nrOffers + $increment) > $maxOffers) {
				return false;
			} else {
				return true;
			}
		} else {
			return false;
		}

		return true;
	}

	/**
	 *
	 * save all videos of the offer
	 *
	 * @param $data object the offer details
	 * @param $offerId int the offer id
	 * @throws Exception
	 */
	public function storeVideos($data, $offerId) {
		$table = $this->getTable('OfferVideos');
		$table->deleteAllForOffer($offerId);

		foreach ($data['videos'] as $value) {
			if (empty($value)) {
				continue;
			}

			$row = $this->getTable('OfferVideos');

			$video = new stdClass();
			$video->id =0;
			$video->offerId = $offerId;
			$video->url = $value;

			if (!$row->bind($video)) {
				throw( new Exception($row->getError()) );
				$this->setError($row->getError());
			}
			// Make sure the record is valid
			if (!$row->check()) {
				throw( new Exception($row->getError()) );
				$this->setError($row->getError());
			}

			// Store the web link table to the database
			if (!$row->store()) {
				throw( new Exception($row->getError()) );
				$this->setError($row->getError());
			}
		}
	}

	/**
	 * Method that retrieves custom attributes based on a certain category in order to be
	 * rendered in HTML.
	 * If multilingual is also enabled, it will translate the attributes.
	 *
	 * @param $categoryId int ID of the category
	 * @param $offerId int ID of the offer
	 *
	 * @return string html output
	 */
	public function getAttributesAjax($categoryId, $offerId) {
		$attributesTable = $this->getTable('Attribute');
		$customFields = $attributesTable->getAttributesByCategory($categoryId, ATTRIBUTE_TYPE_OFFER, $offerId);
		$appSettings = JBusinessUtil::getApplicationSettings();

		foreach ($customFields as $val) {
			if (!isset($val->attributeValue)) {
				$val->attributeValue = '';
			}
		}

		if (!empty($customFields)) {
			if ($appSettings->enable_multilingual) {
				JBusinessDirectoryTranslations::updateAttributesTranslation($customFields);
			}

			$renderedContent = AttributeService::renderAttributes($customFields, false, array());
		} else {
			$renderedContent = null;
		}


		return $renderedContent;
	}

	/**
	 * Method that retrieves custom options based on a certain category in order to be
	 * rendered in HTML.
	 *
	 * @param $categoryId int ID of the category
	 * @param $offerId int ID of the offer
	 *
	 * @return string html output
	 */
	public function getSellingOptionsAjax($offerId, $categoryId){
		$sellingOptions = $this->getOfferSellingAttributes($offerId, $categoryId);

		if (!empty($sellingOptions)) {
			$renderedContent = AttributeService::renderOfferStocks($sellingOptions, false, array());
		} else {
			$renderedContent = null;
		}

		return $renderedContent;
	}

	/**
	 * Retrieve Event Listing based on the Listing Id
	 *
	 * @param $companyId int Listing id of the event
	 * @return mixed All listing details
	 */
	public function getListing($companyId) {
		$companyTable = JTable::getInstance("Company", "JTable");
		$company      = $companyTable->getCompany($companyId);

		$appSettings = JBusinessUtil::getApplicationSettings();
		if ($appSettings->limit_cities_regions) {
			$table            = $this->getTable('Company');
			$company->regions = $table->getCompanyRegions($company->id);
			$company->cities  = $table->getCompanyCities($company->id);

			if (!empty($company->regions)) {
				$company->county = $company->regions[0]->name;
			}

			if (!empty($company->cities)) {
				$company->city = $company->cities[0]->name;
			}
		}

		return $company;
	}
}