<?php

namespace Zotlabs\Module;

use App;
use Zotlabs\Web\Controller;
use Zotlabs\Render\Comanche;
use Zotlabs\Lib\Libsync;
use Zotlabs\Lib\Apps;

class Pdledit_gui extends Controller {

	function post() {

		if (!local_channel()) {
			return;
		}

		if (!$_REQUEST['module']) {
			return;
		}

		$module = $_REQUEST['module'];

		$ret = [
			'success' => false,
			'module' => $module
		];

		if ($_REQUEST['reset']) {
			del_pconfig(local_channel(), 'system', 'mod_' . $module . '.pdl');
			Libsync::build_sync_packet();
			$ret['success'] = true;
			json_return_and_die($ret);
		}

		if ($_REQUEST['save']) {
			if (!$_REQUEST['data']) {
				return $ret;
			}

			$data = json_decode($_REQUEST['data'],true);
			$stored_pdl_result = self::get_pdl($module);
			$pdl = $stored_pdl_result['pdl'];

			foreach ($data as $region => $entries) {
				$region_pdl = '';
				foreach ($entries as $entry) {
					$region_pdl .= base64_decode($entry) . "\r\n";
				}
				$pdl = preg_replace('/\[region=' . $region . '\](.*?)\[\/region\]/ism', '[region=' . $region . ']' . "\r\n" . $region_pdl . "\r\n" . '[/region]', $pdl);
			}

			set_pconfig(local_channel(), 'system', 'mod_' . $module . '.pdl', escape_tags($pdl));
			Libsync::build_sync_packet();

			$ret['success'] = true;
			json_return_and_die($ret);
		}

		if ($_REQUEST['save_src']) {
			set_pconfig(local_channel(), 'system', 'mod_' . $module . '.pdl', escape_tags($_REQUEST['src']));
			Libsync::build_sync_packet();

			$ret['success'] = true;
			json_return_and_die($ret);
		}

		if ($_REQUEST['save_template']) {
			if (!$_REQUEST['data']) {
				return $ret;
			}

			$template = $_REQUEST['data'][0]['value'];
			$pdl_result = self::get_pdl($module);
			$stored_template = self::get_template($pdl_result['pdl']);

			if ($template === $stored_template) {
				$ret['success'] = true;
				return $ret;
			}

			$cnt = preg_match("/\[template\](.*?)\[\/template\]/ism", $pdl_result['pdl'], $matches);
			if ($cnt) {
				$pdl = str_replace('[template]' . $stored_template . '[/template]', '[template]' . $template . '[/template]', $pdl_result['pdl']);
			}
			else {
				$pdl = '[template]' . $template . '[/template]' . "\r\n";
				$pdl .= $pdl_result['pdl'];
			}

			set_pconfig(local_channel(), 'system', 'mod_' . $module . '.pdl', escape_tags($pdl));
			Libsync::build_sync_packet();

			$ret['success'] = true;
			json_return_and_die($ret);
		}

	}

	function get() {

		if(! local_channel()) {
			return EMPTY_STR;
		}

		$module = argv(1);

		if (!$module) {
			goaway(z_root() . '/pdledit_gui/hq');
		}

		$pdl_result = self::get_pdl($module);

		$pdl = $pdl_result['pdl'];
		$modified = $pdl_result['modified'];

		if(!$pdl) {
			return t('Layout not found');
		}

		$template = self::get_template($pdl);

		$template_info = self::get_template_info($template);

		if(empty($template_info['contentregion'])) {
			return t('This template does not support pdledi_gui (no content regions defined)');
		}

		App::$page['template'] = $template;

		$regions = self::get_regions($pdl);

		foreach ($regions as $k => $v) {
			$region_str = '';
			if (is_array($v)) {
				ksort($v);
				foreach ($v as $entry) {
					// Get the info from the file and replace entry if we get anything useful
					$widget_info = get_widget_info($entry['name']);
					$entry['name'] = (($widget_info['name']) ? $widget_info['name'] : $entry['name']);
					$entry['desc'] = (($widget_info['description']) ? $widget_info['description'] : $entry['desc']);

					$region_str .= replace_macros(get_markup_template('pdledit_gui_item.tpl'), [
						'$entry' => $entry
					]);
				}
			}
			App::$layout['region_' . $k] = $region_str;
		}

		$templates = self::get_templates();
		$templates_html = replace_macros(get_markup_template('pdledit_gui_templates.tpl'), [
			'$templates' => $templates,
			'$active' => $template
		]);

		$items_html = '';

		//$items_html .= replace_macros(get_markup_template('pdledit_gui_item.tpl'), [
			//'$entry' => [
				//'type' => 'content',
				//'name' => t('Main page content'),
				//'src' => base64_encode('$content')
			//],
			//'$disable_controls' => true
		//]);

		foreach (self::get_widgets($module) as $entry) {
			$items_html .= replace_macros(get_markup_template('pdledit_gui_item.tpl'), [
				'$entry' => $entry,
				'$disable_controls' => true
			]);
		}

		foreach (self::get_menus() as $entry) {
			$items_html .= replace_macros(get_markup_template('pdledit_gui_item.tpl'), [
				'$entry' => $entry,
				'$disable_controls' => true
			]);
		}

		foreach (self::get_blocks() as $entry) {
			$items_html .= replace_macros(get_markup_template('pdledit_gui_item.tpl'), [
				'$entry' => $entry,
				'$disable_controls' => true
			]);
		}

		App::$layout['region_content'] .= replace_macros(get_markup_template('pdledit_gui.tpl'), [
			'$content_regions' => $template_info['contentregion'],
			'$page_src' => base64_encode($pdl),
			'$templates' => base64_encode($templates_html),
			'$modules' => base64_encode(self::get_modules()),
			'$items' => base64_encode($items_html),
			'$module_modified' => $modified,
			'$module' => $module
		]);

	}

	function get_templates() {
		$ret = [];

		$files = glob('view/php/*.php');
		if($files) {
			foreach($files as $f) {
				$name = basename($f, '.php');
				$x = get_template_info($name);
				if(!empty($x['contentregion'])) {
					$ret[] = [
						'name' => $name,
						'desc' => $x['description']
					];
				}
			}
		}

		return $ret;
	}

	function get_modules() {
		$ret = '';
		$arr = [];

		$files = glob('Zotlabs/Module/*.php');
		if($files) {
			foreach($files as $f) {
				$name = lcfirst(basename($f,'.php'));

				if ($name === 'admin' && !is_site_admin()) {
					continue;
				}

				$x = theme_include('mod_' . $name . '.pdl');
				if($x) {
					$arr[] = $name;
				}
			}
		}

		$addons = plugins_installed_list();
		if ($addons) {
			foreach ($addons as $name) {
				if (!Apps::addon_app_installed(local_channel(), $name)) {
					continue;
				}

				$path = 'addon/' . $name . '/mod_' . $name . '.pdl';
				if (file_exists($path)) {
					$arr[] = $name;
				}
			}
		}

		sort($arr);

		foreach ($arr as $name) {
			$ret .= '<div class="mb-2"><a href="pdledit_gui/' . $name . '">' . $name . '</a></div>';
		}

		return $ret;

	}

	function get_widgets($module) {
		$ret = [];


		$checkpaths = [
			'Zotlabs/Widget/*.php'
		];

		$addons = plugins_installed_list();

		if ($addons) {
			foreach ($addons as $name) {
				if (!Apps::addon_app_installed(local_channel(), $name)) {
					continue;
				}

				$path = 'addon/' . $name . '/Widget';
				if (is_dir($path)) {
					$checkpaths[] = $path . '/*.php';
				}
			}
		}

		foreach ($checkpaths as $path) {
			$files = glob($path);

			if($files) {
				foreach($files as $f) {
					$name = lcfirst(basename($f, '.php'));

					$widget_info = get_widget_info($name);
					if ($widget_info['requires'] && strpos($widget_info['requires'], 'admin') !== false && !is_site_admin()) {
						continue;
					}

					if ($widget_info['requires'] && strpos($widget_info['requires'], $module) === false) {
						continue;
					}

					$ret[] = [
						'type' => 'widget',
						'name' => $widget_info['name'] ?? $name,
						'desc' => $widget_info['description'] ?? '',
						'src' => base64_encode('[widget=' . $name . '][/widget]')
					];
				}
			}
		}

		usort($ret, fn($a, $b) => $a['name'] <=> $b['name']);

		return $ret;
	}

	function get_menus() {
		$ret = [];

		$r = q("select * from menu where menu_channel_id = %d and menu_flags = 0",
			intval(local_channel())
		);

		foreach ($r as $rr) {
			$name = $rr['menu_name'];
			$desc = $rr['menu_desc'];
			$ret[] = [
				'type' => 'menu',
				'name' => $name,
				'desc' => $desc,
				'src' => base64_encode('[menu]' . $name . '[/menu]')
			];
		}

		return $ret;
	}

	function get_blocks() {
		$ret = [];

		$r = q("select v, title, summary from item join iconfig on iconfig.iid = item.id and item.uid = %d
			and iconfig.cat = 'system' and iconfig.k = 'BUILDBLOCK'",
			intval(local_channel())
		);

		foreach ($r as $rr) {
			$name = $rr['v'];
			$desc = (($rr['title']) ? $rr['title'] : $rr['summary']);
			$ret[] = [
				'type' => 'block',
				'name' => $name,
				'desc' => $desc,
				'src' => base64_encode('[block]' . $name . '[/block]')
			];
		}

		return $ret;
	}

	function get_template($pdl) {
		$ret = 'default';

		$cnt = preg_match("/\[template\](.*?)\[\/template\]/ism", $pdl, $matches);
		if($cnt && isset($matches[1])) {
			$ret = trim($matches[1]);
		}

		return $ret;
	}

	function get_regions($pdl) {
		$ret = [];
		$supported_regions = ['aside', 'content', 'right_aside'];

		$cnt = preg_match_all("/\[region=(.*?)\](.*?)\[\/region\]/ism", $pdl, $matches, PREG_SET_ORDER);
		if($cnt) {
			foreach($matches as $mtch) {
				if (!in_array($mtch[1], $supported_regions)) {
					continue;
				}
				$ret[$mtch[1]] = self::parse_region($mtch[2]);
			}
		}

		return $ret;
	}

	function parse_region($pdl) {
		$ret = [];

		$cnt = preg_match_all('/\$content\b/ism', $pdl, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE);
		if($cnt) {
			foreach($matches as $mtch) {
				$offset = intval($mtch[0][1]);
				$name = trim($mtch[0][0]);
				//$src = base64url_encode(preg_replace(['/\s*\[/', '/\]\s*/'], ['[', ']'], $mtch[0][0]));
				$src = base64_encode($mtch[0][0]);
				$ret[$offset] = [
					'type' => 'content',
					'name' => t('Main page content'),
					'desc' => t('The main page content can not be edited!'),
					'src' => $src
				];
			}
		}

		$cnt = preg_match_all("/\[menu\](.*?)\[\/menu\]/ism", $pdl, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE);
		if($cnt) {
			foreach($matches as $mtch) {
				$offset = intval($mtch[1][1]);
				$name = trim($mtch[1][0]);
				//$src = base64url_encode(preg_replace(['/\s*\[/', '/\]\s*/'], ['[', ']'], $mtch[0][0]));
				$src = base64_encode($mtch[0][0]);

				$ret[$offset] = [
					'type' => 'menu',
					'name' => $name,
					'desc' => '',
					'src' => $src
				];
			}
		}

		// menu class e.g. [menu=horizontal]my_menu[/menu] or [menu=tabbed]my_menu[/menu]
		// allows different menu renderings to be applied

		//$cnt = preg_match_all("/\[menu=(.*?)\](.*?)\[\/menu\]/ism", $s, $matches, PREG_SET_ORDER);
		//if($cnt) {
			//foreach($matches as $mtch) {
				//$s = str_replace($mtch[0],$this->menu(trim($mtch[2]),$mtch[1]),$s);
			//}
		//}


		$cnt = preg_match_all("/\[block\](.*?)\[\/block\]/ism", $pdl, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE);
		if($cnt) {
			foreach($matches as $mtch) {
				$offset = intval($mtch[1][1]);
				$name = trim($mtch[1][0]);
				//$src = base64url_encode(preg_replace(['/\s*\[/', '/\]\s*/'], ['[', ']'], $mtch[0][0]));
				$src = base64_encode($mtch[0][0]);
				$ret[$offset] = [
					'type' => 'block',
					'name' => $name,
					'desc' => '',
					'src' => $src
				];
			}
		}

		//$cnt = preg_match_all("/\[block=(.*?)\](.*?)\[\/block\]/ism", $s, $matches, PREG_SET_ORDER);
		//if($cnt) {
			//foreach($matches as $mtch) {
				//$s = str_replace($mtch[0],$this->block(trim($mtch[2]),trim($mtch[1])),$s);
			//}
		//}

		//$cnt = preg_match_all("/\[js\](.*?)\[\/js\]/ism", $s, $matches, PREG_SET_ORDER);
		//if($cnt) {
			//foreach($matches as $mtch) {
				//$s = str_replace($mtch[0],$this->js(trim($mtch[1])),$s);
			//}
		//}

		//$cnt = preg_match_all("/\[css\](.*?)\[\/css\]/ism", $s, $matches, PREG_SET_ORDER);
		//if($cnt) {
			//foreach($matches as $mtch) {
				//$s = str_replace($mtch[0],$this->css(trim($mtch[1])),$s);
			//}
		//}

		// need to modify this to accept parameters

		$cnt = preg_match_all("/\[widget=(.*?)\](.*?)\[\/widget\]/ism", $pdl, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE);

		if($cnt) {
			foreach($matches as $mtch) {
				$offset = intval($mtch[1][1]);
				$name = trim($mtch[1][0]);
				//$src = base64url_encode(preg_replace(['/\s*\[/', '/\]\s*/'], ['[', ']'], $mtch[0][0]));
				$src = base64_encode($mtch[0][0]);
				$ret[$offset] = [
					'type' => 'widget',
					'name' => $name,
					'desc' => '',
					'src' => $src
				];
			}
		}

		return $ret;

	}


	/**
	 * @brief Parse template comment in search of template info.
	 *
	 * like
	 * \code
	 *   * Name: MyWidget
	 *   * Description: A widget
	 *   * Version: 1.2.3
	 *   * Author: John <profile url>
	 *   * Author: Jane <email>
	 *   * ContentRegionID: some_id
	 *   * ContentRegionID: some_other_id
	 *   *
	 *\endcode
	 * @param string $template the name of the template
	 * @return array with the information
	 */
	function get_template_info($template){
		$m = [];
		$info = [
			'name' => $template,
			'description' => '',
			'author' => [],
			'maintainer' => [],
			'version' => '',
			'contentregion' => []
		];

		$checkpaths = [
			'view/php/' . $template . '.php',
		];

		$template_found = false;

		foreach ($checkpaths as $path) {
			if (is_file($path)) {
				$template_found = true;
				$f = file_get_contents($path);
				break;
			}
		}

		if(!($template_found && $f))
			return $info;

		$f = escape_tags($f);
		$r = preg_match('|/\*.*\*/|msU', $f, $m);

		if ($r) {
			$ll = explode("\n", $m[0]);
			foreach($ll as $l) {
				$l = trim($l, "\t\n\r */");
				if ($l != ''){
					list($k, $v) = array_map('trim', explode(':', $l, 2));
					$k = strtolower($k);
					if (in_array($k, ['author', 'maintainer'])){
						$r = preg_match('|([^<]+)<([^>]+)>|', $v, $m);
						if ($r) {
							$info[$k][] = array('name' => $m[1], 'link' => $m[2]);
						} else {
							$info[$k][] = array('name' => $v);
						}
					}
					elseif (in_array($k, ['contentregion'])){
						$info[$k][] = array_map('trim', explode(',', $v));
					}
					else {
						$info[$k] = $v;
					}
				}
			}
		}

		return $info;
	}

	function get_pdl($module) {
		$ret = [
			'pdl' => null,
			'modified' => true
		];

		$pdl = 'mod_' . $module . '.pdl';
		$pdl_path = '';

		$ret['pdl'] = get_pconfig(local_channel(), 'system', $pdl);

		if(!$ret['pdl']) {
			$pdl_path = theme_include($pdl);

			if (!$pdl_path) {
				$addon_path = 'addon/' . $module . '/' . $pdl;
				if (file_exists($addon_path)) {
					$pdl_path = $addon_path;
				}
			}

			if ($pdl_path) {
				$ret['pdl'] = file_get_contents($pdl_path);
				$ret['modified'] = false;
			}
		}

		return $ret;
	}
}
