<?php
/**
 * Created by Error202
 * Date: 10.07.2018
 */

namespace backend\controllers;

use core\entities\menu\Menu;
use core\entities\menu\MenuItem;
use core\entities\ModuleRecord;
use core\forms\menu\MenuForm;
use core\forms\menu\MenuItemForm;
use core\forms\menu\MenuSelectForm;
use core\services\menu\MenuItemManageService;
use core\services\menu\MenuManageService;
use yii\filters\AccessControl;
use yii\filters\VerbFilter;
use yii\helpers\Json;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use Yii;

class MenuController extends Controller
{
	public $menu_service;
	public $menu_item_service;

	public function __construct( string $id, $module, MenuManageService $menu_service, MenuItemManageService $menu_item_service, array $config = [] ) {
		parent::__construct( $id, $module, $config );

		$this->menu_service = $menu_service;
		$this->menu_item_service = $menu_item_service;
	}

	public function behaviors(): array
	{
		return [
			'access' => [
				'class' => AccessControl::class,
				'rules' => [
					[
						'actions' => ['create', 'update', 'delete', 'index', 'save-menu-items', 'save-menu-item-data', 'delete-menu-item'],
						'allow' => true,
						'roles' => ['MenuManagement'],
					],
					[    // all the action are accessible to admin
						'allow' => true,
						'roles' => ['admin'],
					],
				],
			],
			'verbs' => [
				'class' => VerbFilter::class,
				'actions' => [
					'delete' => ['POST'],
					'delete-menu-item' => ['POST'],
				],
			],
		];
	}

	public function actionIndex($id = null)
	{
		$menus = Menu::find()->all();

		$form = new MenuSelectForm();
		if ($form->load(Yii::$app->request->get()) && $form->validate()) {
			return $this->redirect(['menu/index', 'id' => $form->id]);
		}
		elseif ($id) {
			$this->createMenuItem(); // create menu item if MenuItemForm sent

			$menu = $this->findModel($id);

			$creatorWidgets = $this->getCreatorWidgets($menu->id);

			return $this->render('menu', [
				'model' => $form,
				'menus' => $menus,
				'menu' => $menu,
				'creator' => $creatorWidgets,
			]);
		}
		else {
			return $this->render('select_menu', [
				'model' => $form,
				'menus' => $menus,
			]);
		}
	}

	public function actionCreate()
	{
		$form = new MenuForm();
		if ($form->load(Yii::$app->request->post()) && $form->validate()) {
			try {
				$menu = $this->menu_service->create($form);
				return $this->redirect(['index', 'id' => $menu->id]);
			} catch (\DomainException $e) {
				Yii::$app->errorHandler->logException($e);
				Yii::$app->session->setFlash('error', $e->getMessage());
			}
		}
		return $this->render('create', [
			'model' => $form,
		]);
	}

	public function actionUpdate($id)
	{
		$menu = $this->findModel($id);

		$form = new MenuForm($menu);
		if ($form->load(Yii::$app->request->post()) && $form->validate()) {
			try {
				$this->menu_service->edit($menu->id, $form);
				return $this->redirect(['index', 'id' => $menu->id]);
			} catch (\DomainException $e) {
				Yii::$app->errorHandler->logException($e);
				Yii::$app->session->setFlash('error', $e->getMessage());
			}
		}
		return $this->render('update', [
			'model' => $form,
			'menu' => $menu,
		]);
	}

	public function actionDelete($id)
	{
		try {
			$this->menu_service->remove($id);
		} catch (\DomainException $e) {
			Yii::$app->errorHandler->logException($e);
			Yii::$app->session->setFlash('error', $e->getMessage());
		}
		return $this->redirect(['index']);
	}

	public function actionDeleteMenuItem()
	{
		Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
		if (Yii::$app->request->isAjax) {
			try {
				$id = Yii::$app->request->post('id');
				$item = $this->findItemModel($id);

				//$this->deleteItem($item);
				$item->delete();

				Yii::$app->session->setFlash('success', Yii::t('menu', 'Menu Item Deleted'));

				return [ 'result' => 'success' ];
			}
			catch (\RuntimeException $e) {
				return [ 'result' => 'error', 'message' => $e->getMessage() ];
			}
		}
		return ['result' => 'error', 'message' => 'Request error'];
	}

	//private function deleteItem(MenuItem $item): void
	//{
		/*if ($item->hasChildren()) {
			$children = $item->children;
			foreach ($children as $child) {
				$this->deleteItem($child);
			}
		}*/
		//$item->delete();
	//}

	public function actionSaveMenuItemData()
	{
		Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
		if (Yii::$app->request->isAjax) {
			try {
				$id = Yii::$app->request->post('id');
				$name = Yii::$app->request->post('name');
				$title = Yii::$app->request->post('title');
				$style = Yii::$app->request->post('style');
				$css = Yii::$app->request->post('css');
				$url = Yii::$app->request->post('url');
				$target = Yii::$app->request->post('target');

				$item = $this->findItemModel($id);
				$item->name = $name;
				$item->title_attr = $title;
				$item->style = $style;
				$item->css = $css;
				$item->url = $url;
				$item->target = $target;
				$item->save();

				Yii::$app->session->setFlash('success', Yii::t('menu', 'Menu Item Saved'));

				return [ 'result' => 'success' ];
			}
			catch (\RuntimeException $e) {
				return [ 'result' => 'error', 'message' => $e->getMessage() ];
			}
		}
		return ['result' => 'error', 'message' => 'Request error'];
	}

	public function actionSaveMenuItems()
	{
		$json = Yii::$app->request->post('json');
		Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
		if (Yii::$app->request->isAjax) {
			try {
				$order = [];
				$items = Json::decode($json, true);
				foreach ($items as $item) {
					$order[$item[1]] = isset($order[$item[1]]) ? $order[$item[1]]+1 : 0;
					$this->menu_item_service->setPosition($item, $order[$item[1]]);
				}
				Yii::$app->session->setFlash('success', Yii::t('menu', 'Menu Saved'));
				return [ 'result' => 'success' ];
			}
			catch (\RuntimeException $e) {
				return [ 'result' => 'error', 'message' => $e->getMessage() ];
			}
		}
		return ['result' => 'error', 'message' => 'Request error'];
	}

	private function getCreatorWidgets($menu_id): array
	{
		$widgets = [];
		$modules = ModuleRecord::find()->active()->all();
		foreach ($modules as $module) {
			if (method_exists($module->class, 'getMenuItemCreator')) {
				$module_widgets = call_user_func_array($module->class . '::getMenuItemCreator', [$menu_id]);
				$widgets = is_array($module_widgets) ? array_merge($widgets, $module_widgets) : $widgets;
			}
		}
		return $widgets;
	}

	private function createMenuItem()
	{
		$form = new MenuItemForm();
		if ($form->load(Yii::$app->request->post()) && $form->validate()) {
			try {
				$this->menu_item_service->create($form);
			} catch (\DomainException $e) {
				Yii::$app->errorHandler->logException($e);
			}
		}
	}

	protected function findModel($id): Menu
	{
		if (($model = Menu::findOne($id)) !== null) {
			return $model;
		}
		throw new NotFoundHttpException('The requested menu does not exist.');
	}

	protected function findItemModel($id): MenuItem
	{
		if (($model = MenuItem::findOne($id)) !== null) {
			return $model;
		}
		throw new NotFoundHttpException('The requested menu item does not exist.');
	}
}