<?php namespace ProcessWire;

require_once(dirname(__FILE__) . '/FieldtypeLanguageInterface.php'); 

/**
 * Multi-language capable text field
 *
 * ProcessWire 3.x, Copyright 2023 by Ryan Cramer
 * https://processwire.com
 *
 *
 */

class FieldtypeTextLanguage extends FieldtypeText implements FieldtypeLanguageInterface {

	public static function getModuleInfo() {
		return array(
			'title' => 'Text (Multi-language)',
			'version' => 100,
			'summary' => 'Field that stores a single line of text in multiple languages',
			'permanent' => false,
			'requires' => array('LanguageSupportFields'),
		);
	}

	/**
	 * Sanitize value for storage
	 *
	 * @param Page $page
	 * @param Field $field
	 * @param LanguagesValueInterface|string $value
	 * @return LanguagesPageFieldValue
	 *
	 */
	public function sanitizeValue(Page $page, Field $field, $value) {

		if($value instanceof LanguagesPageFieldValue) {
			// great, already what we wanted
			return $value;
		}

		// convert it to a LanguagesPageFieldValue
		$pageValue = $page->data($field->name); // raw unformatted value, with no load possible

		if(!$pageValue instanceof LanguagesPageFieldValue) {
			$pageValue = new LanguagesPageFieldValue($page, $field, $pageValue); // #98
		}

		if(is_array($value)) {
			$pageValue->importArray($value);
			return $pageValue;
		}

		$user = $this->wire()->user;
		$language = $user ? $user->language : null;
		$template = $page->template;

		if(!$language) return $pageValue;

		if($template && $template->noLang) {
			$languages = $this->wire()->languages;
			$pageValue->setLanguageValue($languages->getDefault()->id, (string) $value);
		} else {
			$pageValue->setLanguageValue($language->id, (string) $value);
		}

		return $pageValue;
	}


	/**
	 * Return the database schema in specified format
	 * 
	 * @param Field $field
	 * @return array
	 *
	 */
	public function getDatabaseSchema(Field $field) {
	
		$schema = parent::getDatabaseSchema($field);
		/** @var LanguageSupport $languageSupport */
		$languageSupport = $this->wire()->modules->get('LanguageSupport'); 
		$maxIndex = (int) $this->wire()->database->getMaxIndexLength();
	
		// note that we use otherLanguagePageIDs rather than wire('languages') because
		// it's possible that this method may be called before the languages are known 
		foreach($languageSupport->otherLanguagePageIDs as $languageID) {
			// $schema['data' . $languageID] = $schema['data'];
			$schema['data' . $languageID] = 'text';
			$schema['keys']["data_exact{$languageID}"] = "KEY `data_exact{$languageID}` (`data{$languageID}`($maxIndex))";
			$schema['keys']["data{$languageID}"] = "FULLTEXT KEY `data{$languageID}` (`data{$languageID}`)";
		}
	
		return $schema;
	}

	/**
	 * Format value for output, basically typecasting to a string and sending to textformatters from FieldtypeText
	 * 
	 * @param Page $page
	 * @param Field $field
	 * @param LanguagesValueInterface|string $value
	 * @return string
	 *
	 */
	public function formatValue(Page $page, Field $field, $value) {
		return parent::formatValue($page, $field, (string) $value); 
	}

	/**
	 * Given a value, return an portable version of it as array
	 *
	 * @param Page $page
	 * @param Field $field
	 * @param string|int|float|array|object|null $value
	 * @param array $options Optional settings to shape the exported value, if needed.
	 * @return array
	 *
	 */
	public function ___exportValue(Page $page, Field $field, $value, array $options = array()) {
		$languages = $this->wire()->languages;
		if(isset($options['sleepValue'])) {
			// allow a sleepValue option, for use by other language Fieldtypes that delegate
			// their exportValue to this one, like FieldtypeTextareaLanguage
			$sleepValue = $options['sleepValue'];
		} else {
			$sleepValue = $this->sleepValue($page, $field, $value);
		}
		$exportValue = array();
		foreach($sleepValue as $k => $v) {
			if($k === 'data') {
				$exportValue['default'] = $v;
			} else if(strpos($k, 'data') === 0) {
				$languageID = substr($k, 4);
				$language = $languages->get((int) $languageID);
				$exportValue[$language->name] = $v;
			} else {
				$exportValue[$k] = $v;
			}
		}
		return $exportValue;
	}
	
	public function ___importValue(Page $page, Field $field, $value, array $options = array()) {
		if(is_null($value)) $value = '';
		if(is_string($value)) {
			$v = $value;
			$value = $field->type->exportValue($page, $field, $page->getUnformatted($field->name), $options);
			$value['default'] = $v; 
		}
		if(!is_array($value)) {
			throw new WireException("Array value expected for multi-language importValue");
		}
		$languages = $this->wire()->languages;
		/** @var LanguagesPageFieldValue $importValue */
		$importValue = $page->get($field->name); 
		foreach($value as $languageName => $languageValue) {
			$language = $languages->get($languageName); 
			if(!$language->id) continue; 
			$importValue->setLanguageValue($language->id, $languageValue); 
		}
		return $importValue;
	}

}
