<?php

class AdapterFactory {

	var $model = null;
	var $conditions = array();
	var $adapter = null;


# ~ Initialize adapter - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
	public function initializeAdapter($type, $model) {
		# Store model
		$this->model = $model;

		# Load custom adapter
		$className = ucfirst($type) . 'Adapter';
		require_once(__DIR__ . DS . 'Adapters' . DS . $className . '.php');

		# Initialize adapter
		$this->adapter = new $className();

		return $this;
	}


# ~ Set export conditions- - - - - - - - - - - - - - - - - - - - - - - - - - - #
	public function setConditions($conditions = array()) {
		$this->conditions = $conditions;
		return $this;
	}


# ~ Export data- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
	public function export($filename = 'export') {
		$data = $this->__generateData();
		return $this->adapter->export($data['data'], $data['columns'], $filename);
	}


# ~ Generate data for export - - - - - - - - - - - - - - - - - - - - - - - - - #
	private function __generateData() {

		$instanceCache = array();

		# Get records
		$records = $this->model->find('all', array(
			'conditions' => $this->conditions
		));

		$languages = Configure::read('Config.Languages');

		# Exclude CMS fields
		$schemaFields = $this->model->_schema;
		$columns = array();

		foreach($schemaFields as $field => $options) {
			# Exclude polyglotted fields
			if(substr($field, -4, 2) == '__') continue;

			# Exclude reserved fields
			if(in_array($field, $this->model->_locked) || in_array($field, $this->model->_invisible) || in_array($field, $this->model->reserved['Fields'])) continue;

			# Parse polyglot fields
			if(in_array($field, $this->model->polyglotFields)) {
				foreach($languages as $locale => $langInfo) {
					$columns[$field . '__' . $locale] = Inflector::humanize($field) . ' ' . $langInfo['Language']['title'];
				}
				continue;
			}
			$columns[$field] = Inflector::humanize($field);
		}

		# BelongsTo fields
		foreach($this->model->belongsTo as $association => $settings) {
			$instanceCache[$settings['className']] = ClassRegistry::init($settings['className']);
			$columns[Inflector::singularize(Inflector::tableize($association))] = Inflector::humanize(Inflector::underscore($association));
			unset($columns[$settings['foreignKey']]);
		}


		# HasOne fields
		foreach($this->model->hasOne as $association => $settings) {
			if($settings['className'] == 'Upload') {
				$columns[Inflector::singularize(Inflector::tableize($association))] = Inflector::humanize(Inflector::underscore($association));
			}
		}

		# Generate array for export
		$data = array();
		foreach($records as $index => $record) {
			# BelongsTo
			foreach($this->model->belongsTo as $association => $settings) {
				$record[$this->model->alias][Inflector::singularize(Inflector::tableize($association))] = $record[$association][$instanceCache[$settings['className']]->displayField];
			}

			# hasOne
			foreach($this->model->hasOne as $association => $settings) {
				if($settings['className'] == 'Upload') {
					$record[$this->model->alias][Inflector::singularize(Inflector::tableize($association))] = !empty($record[$association]['file']) ? FULL_BASE_URL . $record[$association]['file'] : '';
				}
			}

			# Handle polyglot fields
			foreach($this->model->polyglotFields as $field) {
				foreach($languages as $locale => $langInfo) {
					$record[$this->model->alias][$field . '__' . $locale] = $record[$this->model->alias][$field . '__'][$locale];
				}
			}

			# Filter items from array
			$data[] = array_intersect_key($record[$this->model->alias], $columns);
		}

		return compact('columns', 'data');
	}

}
