<?php namespace ProcessWire;

/**
 * Installer and uninstaller for LanguageSupport module
 *
 * Split off into a seprate class/file because it's only needed once and 
 * didn't want to keep all this code in the main module that's loaded every request.
 *
 * ProcessWire 3.x, Copyright 2016 by Ryan Cramer
 * https://processwire.com
 * 
 * @method void install()
 * @method void uninstall()
 *
 *
 */

class LanguageSupportInstall extends Wire { 

	/**
	 * Install the module and related modules
	 *
	 */
	public function ___install() {

		$configData = array();

		if($this->templates->get(LanguageSupport::languageTemplateName)) 
			throw new WireException("There is already a template installed called 'language'"); 

		if($this->fields->get(LanguageSupport::languageFieldName)) 
			throw new WireException("There is already a field installed called 'language'"); 

		$adminPage = $this->pages->get($this->config->adminRootPageID); 
		$setupPage = $adminPage->child("name=setup"); 
		if(!$setupPage->id) throw new WireException("Unable to locate {$adminPage->path}setup/"); 

		// create the languages parent page
		$languagesPage = $this->wire('pages')->newPage('admin');
		$languagesPage->parent = $setupPage; 
		$languagesPage->process = $this->modules->get('ProcessLanguage'); // INSTALL ProcessLanguage module
		$this->message("Installed ProcessLanguage"); 
		$languagesPage->name = 'languages';
		$languagesPage->title = 'Languages';
		$languagesPage->status = Page::statusSystem; 
		$languagesPage->sort = $setupPage->numChildren; 
		$languagesPage->save();
		$configData['languagesPageID'] = $languagesPage->id; 
		

		// create the fieldgroup to be used by the language template
		/** @var Fieldgroup $fieldgroup */
		$fieldgroup = $this->wire(new Fieldgroup()); 
		$fieldgroup->name = LanguageSupport::languageTemplateName;
		$fieldgroup->add($this->fields->get('title'));
		$fieldgroup->save();
		$this->message("Created fieldgroup: " . LanguageSupport::languageTemplateName . " ($fieldgroup->id)");

		$this->addFilesFields($fieldgroup);

		// create the template used by Language pages
		/** @var Template $template */
		$template = $this->wire(new Template());	
		$template->name = LanguageSupport::languageTemplateName;
		$template->fieldgroup = $fieldgroup; 
		$template->parentTemplates = array($adminPage->template->id); 
		$template->slashUrls = 1; 
		$template->pageClass = 'Language';
		$template->pageLabelField = 'name';
		$template->noGlobal = 1; 
		$template->noMove = 1; 
		$template->noTrash = 1; 
		$template->noUnpublish = 1; 
		$template->noChangeTemplate = 1; 
		$template->nameContentTab = 1; 
		$template->flags = Template::flagSystem; 
		$template->save();
		$this->message("Created Template: " . LanguageSupport::languageTemplateName); 

		// create the default language page
		$default = $this->wire(new Language());
		$default->template = $template; 
		$default->parent = $languagesPage; 
		$default->name = 'default';
		$default->title = 'Default'; 
		$default->status = Page::statusSystem; 
		$default->save();
		$configData['defaultLanguagePageID'] = $default->id; 
		$configData['otherLanguagePageIDs'] = array(); // non-default language IDs placeholder
		$this->message("Created Default Language Page: {$default->path}"); 

		// create the translator page and process
		$translatorPage = $this->wire('pages')->newPage('admin');
		$translatorPage->parent = $setupPage; 
		$translatorPage->status = Page::statusHidden | Page::statusSystem; 
		$translatorPage->process = $this->modules->get('ProcessLanguageTranslator'); // INSTALL ProcessLanguageTranslator
		$this->message("Installed ProcessLanguageTranslator"); 
		$translatorPage->name = 'language-translator';
		$translatorPage->title = 'Language Translator';
		$translatorPage->save();
		$configData['languageTranslatorPageID'] = $translatorPage->id; 
		$this->message("Created Language Translator Page: {$translatorPage->path}"); 

		// save the module config data
		$this->modules->saveModuleConfigData('LanguageSupport', $configData); 
		
		// install 'language' field that will be added to the user fieldgroup
		$field = $this->wire(new Field()); 
		$field->type = $this->modules->get("FieldtypePage"); 
		$field->name = LanguageSupport::languageFieldName; 
		$field->label = 'Language';
		$field->derefAsPage = 1; 	
		$field->parent_id = $languagesPage->id; 
		$field->labelFieldName = 'title';
		$field->inputfield = 'InputfieldRadios';
		$field->required = 1; 
		$field->flags = Field::flagSystem | Field::flagPermanent; 
		$field->save();
		$this->message("Created Langage Field: " . LanguageSupport::languageFieldName); 

		// make the 'language' field part of the profile fields the user may edit
		$profileConfig = $this->modules->getModuleConfigData('ProcessProfile'); 	
		$profileConfig['profileFields'][] = 'language';
		$this->modules->saveModuleConfigData('ProcessProfile', $profileConfig); 

		// add to 'user' fieldgroup
		$userFieldgroup = $this->templates->get('user')->fieldgroup; 
		$userFieldgroup->add($field); 
		$userFieldgroup->save();
		$this->message("Added field 'language' to user profile"); 

		// update all users to have the default value set for this field
		$n = 0; 
		foreach($this->users as $user) {
			$user->set('language', $default);
			$user->save();
			$n++;
		}

		$this->message("Added default language to $n user profiles"); 

		$this->message("Language Support Installed! Click to the 'Setup' menu to begin defining languages."); 

	}

	/**
	 * @param Fieldgroup $fieldgroup
	 * 
	 */
	public function addFilesFields($fieldgroup) {
		
		// create the 'language_files_site' field used by the 'language' fieldgroup
		/** @var FieldtypeFile $field */
		$field = $this->wire('fields')->get('language_files_site');
		if(!$field) {
			$field = $this->wire(new Field());
			$field->type = $this->modules->get("FieldtypeFile");
			$field->name = 'language_files_site';
			$field->label = 'Site Translation Files';
			$field->extensions = 'json';
			$field->maxFiles = 0;
			$field->inputfieldClass = 'InputfieldFile';
			$field->unzip = 1;
			$field->flags = Field::flagSystem | Field::flagPermanent;
			$field->save();
			$this->message("Created field: language_files_site");
		}
		// update
		$field->label = 'Site Translation Files';
		$field->description = 'Use this field for translations specific to your site (like files in /site/templates/ for example).';
		$field->descriptionRows = 0;
		$field->save();
		$fieldgroup->add($field);
		
		// create the 'language_files' field used by the 'language' fieldgroup
		$field = $this->wire('fields')->get('language_files');
		if(!$field) {
			$field = $this->wire(new Field());
			$field->type = $this->modules->get("FieldtypeFile");
			$field->name = 'language_files';
			$field->label = 'Core Translation Files';
			$field->extensions = 'json';
			$field->maxFiles = 0;
			$field->inputfieldClass = 'InputfieldFile';
			$field->unzip = 1;
			$field->flags = Field::flagSystem | Field::flagPermanent;
			$field->save();
			$this->message("Created field: language_files");
		}
		// update
		$field->label = 'Core Translation Files';
		$field->description = 'Use this field for [language packs](http://modules.processwire.com/categories/language-pack/). To delete all files, double-click the trash can for any file, then save.';
		$field->descriptionRows = 0;
		$field->save();
		$fieldgroup->add($field); 
		
		$fieldgroup->save();
	}

	/**
	 * Uninstall the module and related modules
	 *
	 */
	public function ___uninstall() {

		$language = $this->wire('user')->language; 
		if($language && $language->id && !$language->isDefault) throw new WireException("Please switch your language back to the default language before uninstalling"); 

		// uninstall the components 1 by 1
		$configData = $this->wire('modules')->getModuleConfigData('LanguageSupport'); 

		$field = $this->fields->get(LanguageSupport::languageFieldName); 
		if($field) { 
			$field->flags = Field::flagSystemOverride; 
			$field->flags = 0; 
			$userFieldgroup = $this->templates->get('user')->fieldgroup; 
			if($userFieldgroup) { 
				$userFieldgroup->remove($field); 
				$userFieldgroup->save();
				$this->message("Removed language field from user profiles"); 
			}
			$this->fields->delete($field); 	
			$this->message("Removing field: $field"); 
		}

		$deletePageIDs = array(
			$configData['defaultLanguagePageID'],
			$configData['languageTranslatorPageID'],
			$configData['languagesPageID']
			);

		// remove any language pages that are in the trash		
		$trashLanguages = $this->wire('pages')->get($this->wire('config')->trashPageID)->find("include=all, template=" . LanguageSupport::languageTemplateName); 
		foreach($trashLanguages as $p) $deletePageIDs[] = $p->id; 

		foreach($deletePageIDs as $id) {
			$page = $this->pages->get($id); 
			if(!$page->id) continue; 
			$page->status = Page::statusSystemOverride; 
			$page->status = 0;
			$this->message("Removing page: {$page->path}"); 
			$this->pages->delete($page, true); 
		}

		$template = $this->templates->get(LanguageSupport::languageTemplateName); 	
		if($template) { 
			$template->flags = Template::flagSystemOverride; 
			$template->flags = 0;

			$this->message("Removing template: {$template->name}"); 
			$this->templates->delete($template); 
		}

		$fieldgroup = $this->fieldgroups->get(LanguageSupport::languageTemplateName); 
		if($fieldgroup) { 
			$this->message("Removing fieldgroup: $fieldgroup"); 
			$this->fieldgroups->delete($fieldgroup); 
		}

		$field = $this->fields->get("language_files"); 
		if($field) { 
			$field->flags = Field::flagSystemOverride; 
			$field->flags = 0;
			$this->message("Removing field: {$field->name}"); 
			$this->fields->delete($field); 
		}
		
		$field = $this->fields->get("language_files_site");
		if($field) {
			$field->flags = Field::flagSystemOverride;
			$field->flags = 0;
			$this->message("Removing field: {$field->name}");
			$this->fields->delete($field);
		}

		$this->wire('languages', false);
		$uninstallModules = array('ProcessLanguage', 'ProcessLanguageTranslator'); 
		foreach($uninstallModules as $name) {
			$this->modules->uninstall($name); 
			$this->message("Uninstalled Module: $name"); 
		}

	}


	/**
	 * @return InputfieldWrapper
	 * 
	 */
	public function getModuleConfigInputfields() {
		$modules = $this->wire()->modules;
		$install = $this->_('Click to install:') . ' ';

		$form = $this->wire(new InputfieldWrapper());
		$names = array(
			'LanguageSupportFields',
			'LanguageSupportPageNames',
			'LanguageTabs',
		);
		$installed = array();
		$list = array();

		foreach($names as $name) {
			if($modules->isInstalled($name)) continue;
			$list[$modules->getModuleInstallUrl($name)] = "$install $name";
			$installed[$name] = true;
		}
		
		$list["../setup/languages/"] =
			$this->_('Add and configure new languages');

		$title = $this->wire()->fields->get('title');
		if($title && strpos($title->type->className(), 'Language') === false) {
			$list[$title->editUrl()] =
				$this->_('Change the type of your "title" field from "Page Title" to "Page Title (Multi-language)"') . ' *';
		}

		$list["../setup/field/?fieldtype=FieldtypeText"] =
			$this->_('Change the type of any other desired "Text" fields to "Text (Multi-language)"') . ' *';
		$list["../setup/field/?fieldtype=FieldtypeTextarea"] =
			$this->_('Change the type of any other desired "Textarea" fields to "Textarea (Multi-language)"') . ' *';

		if(count($list)) {
			$jQueryUI = $modules->get('JqueryUI'); /** @var JqueryUI $jQueryUI */
			$jQueryUI->use('modal');
			/** @var InputfieldMarkup $f */
			$f = $modules->get('InputfieldMarkup');
			$f->attr('name', '_next_steps');
			$f->label = $this->_('Next steps');
			$f->value = "<ul>";
			foreach($list as $url => $text) {
				$f->value .= "<li><a target='_blank' href='$url'>$text</a></li>";
			}
			$f->value .= "</ul>";
			$f->description = 
				$this->_('To continue setting up multi-language support, we recommend the following next steps.') . ' ' . 
				$this->_('The links below will open in a new window/tab. Close each after finishing to return here.'); 
			$f->notes = '*' . $this->_('Install the LanguageSupportFields module before attempting to change text field types.');
			$form->add($f);
		}

		return $form; 
	}
}
