<?php
/**
 * Product_import.php
 *
 * 
 * @license	http://opensource.org/licenses/osl-3.0.php open software license (OSL 3.0)
 */

class CC_ImportProduct_Model_Convert_Adapter_Product extends Mage_Catalog_Model_Convert_Adapter_Product
{

	/**
	 * Save product (import)
	 *
	 * @param array $importData
	 * @throws Mage_Core_Exception
	 * @return bool
	 */
	protected $custom_options = array();
	public function saveRow( array $importData )
	{
		$product = $this -> getProductModel();
		$product -> setData( array() );

		if ( $stockItem = $product -> getStockItem() ) {
			$stockItem -> setData( array() );
		}

		if ( empty( $importData['store'] ) ) {
			if ( !is_null( $this -> getBatchParams( 'store' ) ) ) {
				$store = $this -> getStoreById( $this -> getBatchParams( 'store' ) );
			} else {
				$message = Mage :: helper( 'catalog' ) -> __( 'Skip import row, required field "%s" not defined', 'store' );
				Mage :: throwException( $message );
			}
		} else {
			$store = $this -> getStoreByCode( $importData['store'] );
		}

		if ( $store === false ) {
			$message = Mage :: helper( 'catalog' ) -> __( 'Skip import row, store "%s" field not exists', $importData['store'] );
			Mage :: throwException( $message );
		}

		if ( empty( $importData['sku'] ) ) {
			$message = Mage :: helper( 'catalog' ) -> __( 'Skip import row, required field "%s" not defined', 'sku' );
			Mage :: throwException( $message );
		}

		$product->setStoreId( $store -> getId() );
		$productId = $product->getIdBySku( $importData['sku'] );

		if ( $productId ) {
			$product -> load( $productId );
		}
		$productTypes = $this -> getProductTypes();
		$productAttributeSets = $this -> getProductAttributeSets();

		// delete disabled products
		if ( $importData['status'] == 'Disabled' ) {
			$product = Mage :: getSingleton( 'catalog/product' ) -> load( $productId );
			$this -> _removeFile( Mage :: getSingleton( 'catalog/product_media_config' ) -> getMediaPath( $product -> getData( 'image' ) ) );
			$this -> _removeFile( Mage :: getSingleton( 'catalog/product_media_config' ) -> getMediaPath( $product -> getData( 'small_image' ) ) );
			$this -> _removeFile( Mage :: getSingleton( 'catalog/product_media_config' ) -> getMediaPath( $product -> getData( 'thumbnail' ) ) );
			$media_gallery = $product -> getData( 'media_gallery' );
			foreach ( $media_gallery['images'] as $image ) {
				$this -> _removeFile( Mage :: getSingleton( 'catalog/product_media_config' ) -> getMediaPath( $image['file'] ) );
			}
			$product -> delete();
			return true;
		}

		if ( empty( $importData['type'] ) || !isset( $productTypes[strtolower( $importData['type'] )] ) ) {
			$value = isset( $importData['type'] ) ? $importData['type'] : '';
			$message = Mage :: helper( 'catalog' ) -> __( 'Skip import row, is not valid value "%s" for field "%s"', $value, 'type' );
			Mage :: throwException( $message );
		}
		$product -> setTypeId( $productTypes[strtolower( $importData['type'] )] );

		if ( empty( $importData['attribute_set'] ) || !isset( $productAttributeSets[$importData['attribute_set']] ) ) {
			$value = isset( $importData['attribute_set'] ) ? $importData['attribute_set'] : '';
			$message = Mage :: helper( 'catalog' ) -> __( 'Skip import row, is not valid value "%s" for field "%s"', $value, 'attribute_set' );
			Mage :: throwException( $message );
		}
		$product -> setAttributeSetId( $productAttributeSets[$importData['attribute_set']] );

		foreach ( $this -> _requiredFields as $field ) {
			$attribute = $this -> getAttribute( $field );
			if ( !isset( $importData[$field] ) && $attribute && $attribute -> getIsRequired() ) {
				$message = Mage :: helper( 'catalog' ) -> __( 'Skip import row, required field "%s" for new products not defined', $field );
				Mage :: throwException( $message );
			}
		}
		$this->setProductTypeInstance($product);//from cap
		if ($importData['type'] == 'configurable') {
			$product->setCanSaveConfigurableAttributes(true);
			$configAttributeCodes = $this->userCSVDataAsArray($importData['config_attributes']);
			$usingAttributeIds = array();

			/***
			 * Check the product's super attributes (see catalog_product_super_attribute table), and make a determination that way.
			**/
			$cspa  = $product->getTypeInstance()->getConfigurableAttributesAsArray($product);
			$attr_codes = array();
			if(isset($cspa) && !empty($cspa)){ //found attributes
				foreach($cspa as $cs_attr){
					$attr_codes[$cs_attr['attribute_id']] = strtolower($cs_attr['attribute_code']);
					//$attr_codes[] = $cs_attr['attribute_id'];
				}
			}

			foreach($configAttributeCodes as $attributeCode) {
				$attribute = $product->getResource()->getAttribute($attributeCode);
				if ($product->getTypeInstance()->canUseAttribute($attribute)) {
					if (!in_array($attributeCode,$attr_codes)) { // fix for duplicating attributes error
						$usingAttributeIds[] = $attribute->getAttributeId();
					}
				}
			}
			if ( !empty( $usingAttributeIds ) ) {
				$product -> getTypeInstance() -> setUsedProductAttributeIds( $usingAttributeIds );
				$attributes_array = $product->getTypeInstance()->getConfigurableAttributesAsArray();
				foreach($attributes_array as $key => $attribute_value) {
					$attributes_array[$key]['label'] = $attribute_value['frontend_label'];
				}
				$product -> setConfigurableAttributesData($attributes_array);
				$product -> setCanSaveConfigurableAttributes( true );
				$product -> setCanSaveCustomOptions( true );
			}
			if (isset($importData['associated'])) {
				$product->setConfigurableProductsData($this->skusToIds($importData['associated'], $product));
			}
		}//End config
		//begin relate
		if ( isset( $importData['related'] ) ) {
			$linkIds = $this -> skusToIds( $importData['related'], $product );
			if ( !empty( $linkIds ) ) {
				$product -> setRelatedLinkData( $linkIds );
			}
		}

		if ( isset( $importData['upsell'] ) ) {
			$linkIds = $this -> skusToIds( $importData['upsell'], $product );
			if ( !empty( $linkIds ) ) {
				$product -> setUpSellLinkData( $linkIds );
			}
		}

		if ( isset( $importData['crosssell'] ) ) {
			$linkIds = $this -> skusToIds( $importData['crosssell'], $product );
			if ( !empty( $linkIds ) ) {
				$product -> setCrossSellLinkData( $linkIds );
			}
		}

		if ( isset( $importData['grouped'] ) ) {
			$linkIds = $this -> skusToIds( $importData['grouped'], $product );
			if ( !empty( $linkIds ) ) {
				$product -> setGroupedLinkData( $linkIds );
			}
		}
		//end relate
		//begin categor_ids
		if ( isset( $importData['category_ids'] ) ) {
			$product -> setCategoryIds( $importData['category_ids'] );
		}

		//Tier Prices
		if( isset($importData['tier_prices']) && !empty($importData['tier_prices']) ) {
			$this->_editTierPrices($product, $importData['tier_prices']);
		}


		if ( isset( $importData['categories'] ) ) {
			$categoryIds = $this -> _addCategories( $importData['categories'], $store );
			if ( $categoryIds ) {
				$product -> setCategoryIds( $categoryIds );
			}
		}

		foreach ( $this -> _ignoreFields as $field ) {
			if ( isset( $importData[$field] ) ) {
				unset( $importData[$field] );
			}
		}

		if ( $store -> getId() != 0 ) {
			$websiteIds = $product -> getWebsiteIds();
			if ( !is_array( $websiteIds ) ) {
				$websiteIds = array();
			}
			if ( !in_array( $store -> getWebsiteId(), $websiteIds ) ) {
				$websiteIds[] = $store -> getWebsiteId();
			}
			$product -> setWebsiteIds( $websiteIds );
		}

		if ( isset( $importData['websites'] ) ) {
			$websiteIds = $product -> getWebsiteIds();
			if ( !is_array( $websiteIds ) ) {
				$websiteIds = array();
			}
			$websiteCodes = explode(',', $importData['websites']);
			foreach ( $websiteCodes as $websiteCode ) {
				try {
					$website = Mage :: app() -> getWebsite( trim( $websiteCode ) );
					if ( !in_array( $website -> getId(), $websiteIds ) ) {
						$websiteIds[] = $website -> getId();
					}
				}
				catch (Exception $e) {
				}
			}
			$product -> setWebsiteIds( $websiteIds );
			unset( $websiteIds );
		}

		foreach ( $importData as $field => $value ) {
			if ( in_array( $field, $this -> _inventoryFields ) ) {
				continue;
			}
			if ( in_array( $field, $this -> _imageFields ) ) {
				continue;
			}
				
			$attribute = $this -> getAttribute( $field );
			if ( !$attribute ) {

				if(strpos($field,':')!==FALSE && strlen($value)) {
					$values=explode('|',$value);
					if(count($values)>0) {
						@list($title,$type,$is_required,$sort_order) = explode(':',$field);
						$title = ucfirst(str_replace('_',' ',$title));
						$custom_options[] = array(
								'is_delete'=>0,
								'title'=>$title,
								'previous_group'=>'',
								'previous_type'=>'',
								'type'=>$type,
								'is_require'=>$is_required,
								'sort_order'=>$sort_order,
								'values'=>array()
						);
						foreach($values as $v) {
						 $parts = explode(':',$v);
						 $title = $parts[0];
						 if(count($parts)>1) {
						 	$price_type = $parts[1];
						 } else {
						 	$price_type = 'fixed';
						 }
						 if(count($parts)>2) {
						 	$price = $parts[2];
						 } else {
						 	$price =0;
						 }
						 if(count($parts)>3) {
						 	$sku = $parts[3];
						 } else {
						 	$sku='';
						 }
						 if(count($parts)>4) {
						 	$sort_order = $parts[4];
						 } else {
						 	$sort_order = 0;
						 }
						 switch($type) {
						 	case 'file':
						 		break;

						 	case 'field':
						 	case 'area':
						 		$custom_options[count($custom_options) - 1]['max_characters'] = $sort_order;
						 			

						 	case 'date':
						 	case 'date_time':
						 	case 'time':
						 		$custom_options[count($custom_options) - 1]['price_type'] = $price_type;
						 		$custom_options[count($custom_options) - 1]['price'] = $price;
						 		$custom_options[count($custom_options) - 1]['sku'] = $sku;
						 		break;

						 	case 'drop_down':
						 	case 'radio':
						 	case 'checkbox':
						 	case 'multiple':
						 	default:
						 		$custom_options[count($custom_options) - 1]['values'][]=array(
						 		'is_delete'=>0,
						 		'title'=>$title,
						 		'option_type_id'=>-1,
						 		'price_type'=>$price_type,
						 		'price'=>$price,
						 		'sku'=>$sku,
						 		'sort_order'=>$sort_order,
						 		);
						 		break;
						 }
						}
					}
				}
					
				continue;
			}
				
			$isArray = false;
			$setValue = $value;
				
			if ( $attribute -> getFrontendInput() == 'multiselect' ) {
				$value = explode(self::MULTI_DELIMITER, $value);
				$isArray = true;
				$setValue = array();
			}
				
			if ( $value && $attribute -> getBackendType() == 'decimal' ) {
				$setValue = $this -> getNumber( $value );
			}
				
			if ( $attribute -> usesSource() ) {
				$options = $attribute -> getSource() -> getAllOptions( false );

				if ( $isArray ) {
					foreach ( $options as $item ) {
						if ( in_array( $item['label'], $value ) ) {
							$setValue[] = $item['value'];
						}
					}
				}
				else {
					$setValue = null;
					foreach ( $options as $item ) {
						if ( $item['label'] == $value ) {
							$setValue = $item['value'];
						}
					}
				}
			}
				
			$product -> setData( $field, $setValue );
		}

		if ( !$product -> getVisibility() ) {
			$product -> setVisibility( Mage_Catalog_Model_Product_Visibility :: VISIBILITY_NOT_VISIBLE );
		}

		$stockData = array();
		$inventoryFields = isset($this->_inventoryFieldsProductTypes[$product->getTypeId()])
		? $this->_inventoryFieldsProductTypes[$product->getTypeId()]
		: array();
		foreach ( $inventoryFields as $field ) {
			if ( isset( $importData[$field] ) ) {
				if ( in_array( $field, $this -> _toNumber ) ) {
					$stockData[$field] = $this -> getNumber( $importData[$field] );
				}
				else {
					$stockData[$field] = $importData[$field];
				}
			}
		}
		$product -> setStockData( $stockData );

		//MRD added to remove all images for product before uploading new images
		if(!empty($importData['gallery'])){
			//check if gallery attribute exists then remove all images if it exists
			//Get products gallery attribute
			$attributes = Mage::getSingleton('catalog/product_type')->factory($product)->getSetAttributes();//$product->getTypeInstance()->getSetAttributes();//this will cause the configurable product error
			if (isset($attributes['media_gallery'])) {
				$gallery_to_remove = $attributes['media_gallery'];
				//Get the images
				$galleryData = $product->getMediaGallery();
				foreach($galleryData['images'] as $image){
					//If image exists
					if ($gallery_to_remove->getBackend()->getImage($product, $image['file'])) {
						$gallery_to_remove->getBackend()->removeImage($product, $image['file']);
						//unlink(Mage::getBaseDir('media') . DS . 'catalog' . DS . 'product' . $image['file']);
						$this->_removeFile(Mage::getBaseDir('media') . DS . 'catalog' . DS . 'product' . $image['file']);
					}
				}
			}
			#$gallery_to_remove->clearMediaAttribute($product, array('image','small_image','thumbnail'));
		}
		//END Remove Images


		/*
		 Code for image upload in version 1.5.x.x and above
		*/
		$mediaGalleryBackendModel = $this->getAttribute('media_gallery')->getBackend();

		$arrayToMassAdd = array();

		foreach ($product->getMediaAttributes() as $mediaAttributeCode => $mediaAttribute) {
			if (isset($importData[$mediaAttributeCode])) {
				$file = $importData[$mediaAttributeCode];
				if (trim($file) && !$mediaGalleryBackendModel->getImage($product, $file)) {
					$arrayToMassAdd[] = array('file' => trim($file), 'mediaAttribute' => $mediaAttributeCode);
				}
			}
		}

		$addedFilesCorrespondence =
		$mediaGalleryBackendModel->addImagesWithDifferentMediaAttributes($product, $arrayToMassAdd, Mage::getBaseDir('media') . DS . 'import', false, false);

		foreach ($product->getMediaAttributes() as $mediaAttributeCode => $mediaAttribute) {
			$addedFile = '';
			if (isset($importData[$mediaAttributeCode . '_label'])) {
				$fileLabel = trim($importData[$mediaAttributeCode . '_label']);
				if (isset($importData[$mediaAttributeCode])) {
					$keyInAddedFile = array_search($importData[$mediaAttributeCode],
							$addedFilesCorrespondence['alreadyAddedFiles']);
					if ($keyInAddedFile !== false) {
						$addedFile = $addedFilesCorrespondence['alreadyAddedFilesNames'][$keyInAddedFile];
					}
				}

				if (!$addedFile) {
					$addedFile = $product->getData($mediaAttributeCode);
				}
				if ($fileLabel && $addedFile) {
					$mediaGalleryBackendModel->updateImage($product, $addedFile, array('label' => $fileLabel));
				}
			}
		}

		/**
		 * Allows you to import multiple images for each product.
		 * Simply add a 'gallery' column to the import file, and separate
		 * each image with a semi-colon.
		 */
		try {
			$galleryData = explode(';',$importData["gallery"]);
			foreach($galleryData as $gallery_img)
				/**
				 * @param directory where import image resides
			* @param leave 'null' so that it isn't imported as thumbnail, base, or small
			* @param false = the image is copied, not moved from the import directory to it's new location
			* @param false = not excluded from the front end gallery
			*/
			{
				$product->addImageToMediaGallery(Mage::getBaseDir('media') . DS . 'import' . $gallery_img, null, false, false);
			}
		}
		catch (Exception $e) {
		}

		$product -> setIsMassupdate( true );
		$product -> setExcludeUrlRewrite( true );

		$product -> save();
		$product->cleanCache();
		if(isset($custom_options)){
			foreach ($product->getOptions() as $option) {
				try {
					$option->getValueInstance()->deleteValue($option->getId());
					$option->deletePrices($option->getId());
					$option->deleteTitles($option->getId());
					$option->delete();
				} catch (Exception $e) {
				}
			}


			if(count($custom_options)) {
				foreach($custom_options as $option) {
			  try {
			  	$opt = Mage::getModel('catalog/product_option');
			  	$opt->setProduct($product);
			  	$opt->addOption($option);
			  	$opt->saveOptions();
			  }
			  catch (Exception $e) {
			  }
				}
			}
		}
		return true;
	}
	/**
	 * Edit tier prices
	 *
	 * Uses a pipe-delimited string of qty:price to set tiers for the product row and appends.
	 * Removes if REMOVE is present.
	 *
	 * @todo Prevent duplicate tiers (by qty) being set
	 * @internal Magento will save duplicate tiers; no enforcing unique tiers by qty, so we have to do this manually
	 * @param Mage_Catalog_Model_Product $product Current product row
	 * @param string $tier_prices_field Pipe-separated in the form of qty:price (e.g. 250=12.75|500=12.00)
	 */
	private function _editTierPrices(&$product, $tier_prices_field = false)
	{
		if (($tier_prices_field) && !empty($tier_prices_field)) {
			if(trim($tier_prices_field) == 'REMOVE'){
				$product->setTierPrice(array());
			}
			else {
				//get current product tier prices
				$existing_tps = $product->getTierPrice();

				//make a lookup array to prevent dup tiers by qty
				foreach($existing_tps as $key => $etp){
					$etp_lookup[$etp['price_qty']] = $key;
				}

				//parse incoming tier prices string
				$incoming_tierps = explode('|',$tier_prices_field);
				foreach($incoming_tierps as $tier_str){
					$tmp = explode('=',$tier_str);
					$tps_toAdd[$tmp[0]] = array(
							'website_id' => 0, // !!!! this is hard-coded for now
							'cust_group' => 2, // !!! so is this
							'price_qty' => $tmp[0],
							'price' => $tmp[1],
							'delete' => ''
					);
					//drop any existing tier values by qty
					if(isset($etp_lookup[$tmp[0]])){
						unset($existing_tps[$etp_lookup['price_qty']]);
					}
				}

				//combine array
				$tps_toAdd =  array_merge($existing_tps, $tps_toAdd);
				//save it
				$product->setTierPrice($tps_toAdd);
			}
		}
	}


	protected function userCSVDataAsArray( $data )
	{
		return explode( ',', strtolower(str_replace( " ", "", $data )) );
	}

	protected function skusToIds( $userData, $product )
	{
		$productIds = array();
		foreach ( $this -> userCSVDataAsArray( $userData ) as $oneSku ) {
			if ( ( $a_sku = ( int )$product -> getIdBySku( $oneSku ) ) > 0 ) {
				parse_str( "position=", $productIds[$a_sku] );
			}
		}
		return $productIds;
	}

	protected $_categoryCache = array();


	protected function _addCategories( $categories, $store )
	{
		$rootId = $store->getRootCategoryId();//Don't know why the rootId always get 0
		//$rootId = 2;//13; // our store's root category id
		if ( !$rootId ) {
			$storeId = 1;
			$rootId = Mage::app()->getStore($storeId)->getRootCategoryId();
		}
		if($categories=="")
			return array();
		$rootPath = '1/' . $rootId;
		if ( empty( $this -> _categoryCache[$store -> getId()] ) ) {
			$collection = Mage :: getModel( 'catalog/category' ) -> getCollection()
			-> setStore( $store )
			-> addAttributeToSelect( 'name' );
			$collection -> getSelect() -> where( "path like '" . $rootPath . "/%'" );
			foreach ( $collection as $cat ) {
				try {
					$pathArr = explode( '/', $cat -> getPath() );
					$namePath = '';
					for ( $i = 2, $l = sizeof( $pathArr ); $i < $l; $i++ ) {
						$name = $collection -> getItemById( $pathArr[$i] ) -> getName();
						$namePath .= (empty($namePath) ? '' : '#').trim($name);
					}
					$cat -> setNamePath( $namePath );
				}
				catch ( Exception $e ) {
					echo "ERROR: Cat - ";
					print_r( $cat );
					continue;
				}
			}
				
			$cache = array();
			foreach ( $collection as $cat ) {
				$cache[strtolower( $cat -> getNamePath() )] = $cat;
				$cat -> unsNamePath();
			}
			$this -> _categoryCache[$store -> getId()] = $cache;
		}
		$cache = &$this -> _categoryCache[$store -> getId()];

		$catIds = array();
		foreach (explode('?', $categories) as $categoryPathStr) {
			$categoryPathStr = preg_replace('!\s*#\s*!', '#', trim($categoryPathStr));
			if ( !empty( $cache[$categoryPathStr] ) ) {
				$catIds[] = $cache[$categoryPathStr] -> getId();
				continue;
			}
			$path = $rootPath;
			$namePath = '';
			foreach (explode('#', $categoryPathStr) as $catName) {
				$namePath .= (empty($namePath) ? '' : '#').strtolower($catName);
				if ( empty( $cache[$namePath] ) ) {
					$cat = Mage :: getModel( 'catalog/category' )
					-> setStoreId( $store -> getId() )
					-> setPath( $path )
					-> setName( $catName )
					-> setIsActive( 1 )
					-> save();
					$cache[$namePath] = $cat;
				}
				$catId = $cache[$namePath] -> getId();
				$path .= '/' . $catId;
			}
			if ( $catId ) {
				$catIds[] = $catId;
			}
		}
		return join( ',', $catIds );
	}

	protected function _removeFile( $file )
	{
		if ( file_exists( $file ) ) {
			if ( unlink( $file ) ) {
				return true;
			}
		}
		return false;
	}
}