<?php
/**
 * Copyright 2009 - 2013, Cake Development Corporation (http://cakedc.com)
 *
 * Licensed under The MIT License
 * Redistributions of files must retain the above copyright notice.
 *
 * @copyright Copyright 2009 - 2013, Cake Development Corporation (http://cakedc.com)
 * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
 */

/**
 * Utils Plugin
 *
 * Utils Csv Import Behavior
 *
 * @package utils
 * @subpackage utils.models.behaviors
 */
App::uses('Utils', 'UtilsAppModel');
class CsvImportBehavior extends ModelBehavior {
/**
 * Importable behavior settings
 *
 * @var array
 */
	public $settings = array();

/**
 * List of errors generated by the import action
 *
 * @var array
 */
	public $errors = array();

/**
 * List of objects instances or callables to notify from events on this class
 *
 * @var array
 */
	protected $_subscribers = array();

/**
 * Initializes this behavior for the model $Model
 *
 * @param Model $Model
 * @param array $settings
 * @return void
 */
	public function setup(Model $Model, $settings = array()) {
		if (!isset($this->settings[$Model->alias])) {
			$this->settings[$Model->alias] = array(
				'delimiter' => ',',
				'enclosure' => '"',
				'hasHeader' => true
			);
		}
		$this->settings[$Model->alias] = array_merge($this->settings[$Model->alias], $settings);
	}

/**
 * Returns a line form the CSV file and advances the pointer to the next one
 *
 * @param Model $Model
 * @param SplFileObject $handle CSV file handler
 * @return array list of attributes fetched from the CSV file
 */
	protected function _getCSVLine(Model &$Model, SplFileObject $handle) {
		if ($handle->eof()) {
			return false;
		}
		return $handle->fgetcsv(
			$this->settings[$Model->alias]['delimiter'],
			$this->settings[$Model->alias]['enclosure']
		);
	}

/**
 * Returns a list of keys representing the columns of the CSV file
 *
 * @param Model $Model
 * @param SplFileObject $handle CSV file handler
 * @return array list of attributes fetched from the CSV file
 */
	protected function _getHeader(Model &$Model, SplFileObject $handle) {
		if ($this->settings[$Model->alias]['hasHeader'] === true) {
			$header = $this->_getCSVLine($Model, $handle);
		} else {
			$header = array_keys($Model->schema());
		}
		return $header;
	}

/**
 * Returns a list of keys representing the columns of the CSV file
 *
 * @param Model $Model
 * @param string $file path to the CSV file
 * @param array $fixed data to be merged with every row
 * @param boolean $returnSaved true to return
 * @throws RuntimeException if $file does not exists
 * @return mixed boolean indicating the success of the operation or list of saved records
 */
	public function importCSV(Model &$Model, $file, $fixed = array(), $groupName=array(),$type=null,$siteArr=array(),$returnSaved = false) {
		$handle = new SplFileObject($file, 'rb');
		$header = $this->_getHeader($Model, $handle);
		$db = $Model->getDataSource();
		$db->begin($Model);
		$CustomfunctionComponent= new CustomfunctionComponent(null);
		$saved = array();
		$i = 0;
		while (($row = $this->_getCSVLine($Model, $handle)) !== false) {
			if(count($row)>1)
			{
			$data = array();
			$data1=array();
			foreach ($header as $k => $col) {
				// get the data field from Model.field
				if($col=="qtype_id")
				{
					if($row[$k]=="M")
					$row[$k]=1;
					elseif($row[$k]=="T")
					$row[$k]=2;
					elseif($row[$k]=="F")
					$row[$k]=3;
					elseif($row[$k]=="S")
					$row[$k]=4;
					else
					$row[$k]=1;
				}
				if($col=="diff_id")
				{
					if($row[$k]=="E")
					$row[$k]=1;
					elseif($row[$k]=="M")
					$row[$k]=2;
					elseif($row[$k]=="D")
					$row[$k]=3;					
					else
					$row[$k]=1;
				}
				if (strpos($col, '.') !== false) {
					$keys = explode('.', $col);
					if (isset($keys[2])) {
						$data[$keys[0]][$keys[1]][$keys[2]]= (isset($row[$k])) ? $row[$k] : '';
					} else {
						$data[$keys[0]][$keys[1]]= (isset($row[$k])) ? $row[$k] : '';
					}
				} else {
					$data[$Model->alias][$col]= (isset($row[$k])) ? $row[$k] : '';
				}
			}			
			$data = Set::merge($data, $fixed);
			$Model->create();
			$Model->id = isset($data[$Model->alias][$Model->primaryKey]) ? $data[$Model->alias][$Model->primaryKey] : false;

			//beforeImport callback
			if (method_exists($Model, 'beforeImport')) {
				$data = $Model->beforeImport($data);
			}

			$error = false;
			$Model->set($data);
			if (!$Model->validates()) {
				$this->errors[$Model->alias][$i]['validation'] = $Model->validationErrors;
				$error = true;
				$this->_notify($Model, 'onImportError', $this->errors[$Model->alias][$i]);
			}

			// save the row
			if (!$error && !$Model->saveAll($data, array('validate' => false,'atomic' => false))) {
				$this->errors[$Model->alias][$i]['save'] = sprintf(__d('utils', '%s for Row %d failed to save.'), $Model->alias, $i);
				$error = true;
				$this->_notify($Model, 'onImportError', $this->errors[$Model->alias][$i]);
			}
			if($type!=null)
			{
				if($type=="QuestionGroup")
				{
					$fixedId="question_id";
					foreach($groupName as $groupId)
					{
						$data1[]=array($type=>array($fixedId=>$Model->id,'group_id'=>$groupId));
					}					
				}				
				elseif($type=="StudentGroup")
				{
					$fixedId="student_id";
					foreach($groupName as $groupId)
					{
						$data1[]=array($type=>array($fixedId=>$Model->id,'group_id'=>$groupId));
						$email=$data['Iestudent']['email'];$studentName=$data['Iestudent']['name'];$mobileNo=$data['Iestudent']['phone'];$password="st123456";
						$siteName=$siteArr['siteName'];$siteEmailContact=$siteArr['siteEmailContact'];$url=$siteArr['siteDomain'];$siteEmail=$siteArr['siteEmail'];
						if($email)
						{
						    if($siteArr['emailNotification'])
						    {                          
							/* Send Email */
							$emailTemplateArr=$siteArr['emailTemplate'];
							$emailSettingArr=$siteArr['emailSettingArr'];
							if($emailTemplateArr['Emailtemplate']['status']=="Published")
							{
							    $message=eval('return "' . addslashes($emailTemplateArr['Emailtemplate']['description']) . '";');
							    $Email = new CakeEmail();
							    $Email->transport($emailSettingArr['Emailsetting']['type']);
							    if($emailSettingArr['Emailsetting']['type']=="Smtp")
							    $Email->config(array('host' => $emailSettingArr['Emailsetting']['host'],'port' =>  $emailSettingArr['Emailsetting']['port'],'username' => $emailSettingArr['Emailsetting']['username'],'password' => $emailSettingArr['Emailsetting']['password'],'timeout'=>90));
							    $Email->from(array($siteEmail =>$siteName));
							    $Email->to($email);
							    $Email->template('default');
							    $Email->emailFormat('html');
							    $Email->subject($emailTemplateArr['Emailtemplate']['name']);
							    $Email->send($message);
							    /* End Email */
							}
						    }
						}
						if($siteArr['smsNotification'])
						{
							/* Send Sms */
							$smsTemplateArr=$siteArr['smsTemplate'];
							if($smsTemplateArr['Smstemplate']['status']=="Published")
							{
							    $message=eval('return "' . addslashes($smsTemplateArr['Smstemplate']['description']) . '";');
							   $CustomfunctionComponent->sendSms($mobileNo,$message,$siteArr['smsSettingArr']);
							}
							/* End Sms */
						}
					}					
				}
				$typeGroup=ClassRegistry::init($type);
				$typeGroup->create();
				$typeGroup->saveAll($data1);
			}
			
			if (!$error) {
				$this->_notify($Model, 'onImportRow', $data);
				if ($returnSaved) {
					$saved[] = $i;
				}
			}
			}

			$i++;
		}

		$success = empty($this->errors);
		if (!$returnSaved && !$success) {
			$db->rollback($Model);
			return false;
		}

		$db->commit($Model);

		if ($returnSaved) {
			return $saved;
		}

		return true;
	}

/**
 * Returns the errors generated by last import
 *
 * @param Model $Model
 * @return array
 */
	public function getImportErrors(Model &$Model) {
		if (empty($this->errors[$Model->alias])) {
			return array();
		}
		return $this->errors[$Model->alias];
	}

/**
 * Attachs a new listener for the events generated by this class
 *
 * @param Model $Model
 * @param mixed listener instances of an object or valid php callback
 * @return void
 */
	public function attachImportListener(Model $Model, $listener) {
		$this->_subscribers[$Model->alias][] = $listener;
	}

/**
 * Notifies the listeners of events generated by this class
 *
 * @param Model $Model
 * @param string $action the name of the event. It will be used as method name for object listeners
 * @param mixed $data additional information to pass to the listener callback
 * @return void
 */
	protected function _notify(Model $Model, $action, $data = null) {
		if (empty($this->_subscribers[$Model->alias])) {
			return;
		}
		foreach ($this->_subscribers[$Model->alias] as $object) {
			if (method_exists($object, $action)) {
				$object->{$action}($data);
			}
			if (is_callable($object)) {
				call_user_func($object, $action, $data);
			}
		}
	}
}