<?php
/**
 * webtrees: online genealogy
 * Copyright (C) 2017 webtrees development team
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
namespace Fisharebest\Webtrees\Module\BatchUpdate;

use Fisharebest\Algorithm\MyersDiff;
use Fisharebest\Webtrees\Auth;
use Fisharebest\Webtrees\Bootstrap4;
use Fisharebest\Webtrees\Filter;
use Fisharebest\Webtrees\GedcomRecord;
use Fisharebest\Webtrees\I18N;
use Fisharebest\Webtrees\Module\BatchUpdateModule;

/**
 * Class BatchUpdateBasePlugin
 *
 * Each plugin should extend this class, and implement these two functions:
 *
 * bool doesRecordNeedUpdate($xref, $gedrec)
 * string updateRecord($xref, $gedrec)
 */
class BatchUpdateBasePlugin {
	/** @var bool User option; update change record */
	public $chan = false;

	/**
	 * Default is to operate on INDI records
	 *
	 * @return string[]
	 */
	public function getRecordTypesToUpdate() {
		return ['INDI'];
	}

	/**
	 * Default option is just the "don't update CHAN record"
	 */
	public function getOptions() {
		$this->chan = Filter::getBool('chan');
	}

	/**
	 * Default option is just the "don't update CHAN record"
	 *
	 * @return string
	 */
	public function getOptionsForm() {
		return
			'<div class="row form-group">' .
			'<label class="col-sm-3 col-form-label">' . I18N::translate('Keep the existing “last change” information') . '</label>' .
			'<div class="col-sm-9">' .
			Bootstrap4::radioButtons('chan', [0 => I18N::translate('no'), 1 => I18N::translate('yes')], ($this->chan ? 1 : 0), true, ['onchange' => 'this.form.submit();']) .
			'</div></div>';
	}

	/**
	 * Default buttons are update and update_all
	 *
	 * @param string $xref
	 *
	 * @return string[]
	 */
	public function getActionButtons($xref) {
		if (Auth::user()->getPreference('auto_accept')) {
			return [
				BatchUpdateModule::createSubmitButton(I18N::translate('Update'), $xref, 'update'),
				BatchUpdateModule::createSubmitButton(I18N::translate('Update all'), $xref, 'update_all'),
			];
		} else {
			return [
				BatchUpdateModule::createSubmitButton(I18N::translate('Update'), $xref, 'update'),
			];
		}
	}

	/**
	 * Default previewer for plugins with no custom preview.
	 *
	 * @param GedcomRecord $record
	 *
	 * @return string
	 */
	public function getActionPreview(GedcomRecord $record) {
		$old_lines   = preg_split('/[\n]+/', $record->getGedcom());
		$new_lines   = preg_split('/[\n]+/', $this->updateRecord($record->getXref(), $record->getGedcom()));
		$algorithm   = new MyersDiff;
		$differences = $algorithm->calculate($old_lines, $new_lines);
		$diff_lines  = [];

		foreach ($differences as $difference) {
			switch ($difference[1]) {
				case MyersDiff::DELETE:
					$diff_lines[] = self::decorateDeletedText($difference[0]);
					break;
				case MyersDiff::INSERT:
					$diff_lines[] = self::decorateInsertedText($difference[0]);
					break;
				default:
					$diff_lines[] = $difference[0];
			}
		}

		return '<pre class="gedcom-data">' . self::createEditLinks(implode("\n", $diff_lines), $record) . '</pre>';
	}

	/**
	 * Decorate inserted text
	 *
	 * @param string $text
	 *
	 * @return string
	 */
	public static function decorateInsertedText($text) {
		return '<ins>' . $text . '</ins>';
	}

	/**
	 * Decorate deleted text
	 *
	 * @param string $text
	 *
	 * @return string
	 */
	public static function decorateDeletedText($text) {
		return '<del>' . $text . '</del>';
	}

	/**
	 * Converted gedcom links into editable links
	 *
	 * @param string       $gedrec
	 * @param GedcomRecord $record
	 *
	 * @return string
	 */
	public static function createEditLinks($gedrec, GedcomRecord $record) {
		return preg_replace(
			"/@([^#@\n]+)@/m",
			'<a href="edit_interface.php?action=editraw&amp;ged=' . $record->getTree()->getNameHtml() . '&amp;xref=' . $record->getXref() . '">@\\1@</a>',
			$gedrec
		);
	}
}
