<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Libs\Facades\ContentTypes;
use App\Libs\Facades\Localization;
use App\Libs\Facades\RequestContext;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Menu;
use MenuItem;
use MenuItemLanguage;
use stdClass;
use BigMenu;
use Entry;
use WebsiteObject;

class MenuController extends Controller
{

    public function postCreateMenuItem()
    {
        $type = request()->input('type');
        $website = Localization::getWebsite();
        $languages = $website->languages;
        $defaultLanguage = Localization::getDefaultLocale();

        if ($type === 'object') {
            $objectId = request()->input('website_object_id');
            if (!$objectId || !is_numeric($objectId)) {
                return response()->json(false);
            }

            $websiteObject = WebsiteObject::where('website_id', $website->id)
                ->where('website_object_id', $objectId)
                ->first();
            $object = $websiteObject->objectable;

            $tempMenuItem = new stdClass();
            $tempMenuItem->target = null;
            $tempMenuItem->active = $websiteObject->status == 'published';
            $tempMenuItem->id = 'new_'.rand(0, 3000000);
            $tempMenuItem->entry = null;
            $tempMenuItem->entry_id = null;
            $tempMenuItem->object = $object;
            $tempMenuItem->websiteObject = $websiteObject;
            $tempMenuItem->website_object_id = $websiteObject->website_object_id;
            $tempMenuItem->big_menu_id = null;
            $tempMenuItem->bigMenu = null;
            $tempMenuItem->use_object_title = true;
            $tempMenuItem->languages = array();
            $tempMenuItem->type = 'object';
            foreach ($languages as $language) {
                $itemLang = new stdClass();
                $itemLang->language_id = $language->id;
                $objectLanguage = $object->languages->findByLocale($language->id);
                if ($objectLanguage) {
                    $itemLang->title = $objectLanguage->title;
                } else {
                    $itemLang->title = '';
                }
                if ($websiteObject) {
                    $websiteObjectLang = $websiteObject->languages->findBylocale($language->id);
                    $itemLang->url = $websiteObjectLang->lang_uri;
                }
                $tempMenuItem->languages[] = $itemLang;

                if ($language->id == $defaultLanguage) {
                    $tempMenuItem->title = $objectLanguage->title;
                }
            }
            $viewHtml = view('admin.pages.menus.menu_item')
                ->with('menuItem', $tempMenuItem)
                ->render();
            $result = array(
                'success' => true,
                'menu_item_html' => $viewHtml
            );

            return response()->json($result);
        } else if ($type === 'page') {
            $pageId = request()->input('page_id');
            if (!$pageId || !is_numeric($pageId)) {
                return response()->json(false);
            }

            $page = $website->getEntry($pageId);

            $tempMenuItem = new stdClass();
            //$tempMenuItem->url = $page->uri;
            $tempMenuItem->target = null;
            $tempMenuItem->active = $page->status == 'published';
            $tempMenuItem->id = 'new_'.rand(0, 3000000);
            $tempMenuItem->entry = $page;
            $tempMenuItem->entry_id = $page->id;
            $tempMenuItem->big_menu_id = null;
            $tempMenuItem->bigMenu = null;
            $tempMenuItem->languages = array();
            $tempMenuItem->type = 'page';
            foreach ($languages as $language) {
                $itemLang = new stdClass();
                $itemLang->language_id = $language->id;
                $pageLanguage = $page->languages->findByLocale($language->id);
                $pageWO = $page->websites->findByWebsite($website->id);
                if ($pageLanguage) {
                    $itemLang->title = $pageLanguage->title;
                } else {
                    $itemLang->title = '';
                }
                if ($pageWO) {
                    $pageWOLang = $pageWO->languages->findBylocale($language->id);
                    $itemLang->url = $pageWOLang->lang_uri;
                }
                $tempMenuItem->languages[] = $itemLang;

                if ($language->id == $defaultLanguage) {
                    $tempMenuItem->title = $pageLanguage->title;
                }
            }
            $viewHtml = view('admin.pages.menus.menu_item')
                ->with('menuItem', $tempMenuItem)
                ->render();
            $result = array(
                'success' => true,
                'menu_item_html' => $viewHtml
            );

            return response()->json($result);
        } else if ($type == 'content') {
            $data = array(
                'title' => request()->input('menu_label', ''),
                'big_menu_id' => request()->input('big_menu_id'),
                'url' => request()->input('link_url')
            );
            $validator = Validator::make(
                $data,
                $this->itemRules($type)
            );
            if ($validator->fails()) {
                $result = array(
                    'success' => false,
                    'errors' => $validator->messages()->toArray()
                );
                return response()->json($result);
            }

            $tempMenuItem = new stdClass();
            $tempMenuItem->active = true;
            $tempMenuItem->big_menu_id = $data['big_menu_id'];
            $tempMenuItem->bigMenu = BigMenu::find($tempMenuItem->big_menu_id);
            $tempMenuItem->target = null;
            $tempMenuItem->id = 'new_'.rand(0, 3000000);
            $tempMenuItem->entry = null;
            $tempMenuItem->entry_id = null;
            $tempMenuItem->websiteObject = null;
            $tempMenuItem->website_object_id = null;
            $tempMenuItem->languages = array();
            $tempMenuItem->type = 'content';
            foreach ($data['title'] as $lang => $value) {
                $itemLang = new stdClass();
                $itemLang->language_id = $lang;
                $itemLang->title = $value;
                $itemLang->url = $data['url'][$lang];
                $tempMenuItem->languages[] = $itemLang;

                if ($lang == $defaultLanguage) {
                    $tempMenuItem->title = $value;
                }
            }

            $viewHtml = view('admin.pages.menus.menu_item')
                ->with('menuItem', $tempMenuItem)
                ->render();
            $result = array(
                'success' => true,
                'menu_item_html' => $viewHtml
            );

            return response()->json($result);
        } else {
            if ($type == 'link') {
                $data = array(
                    'title' => request()->input('menu_label', ''),
                    'url' => request()->input('link_url'),
                    'new_window' => request()->input('new_window') == 'true'
                );

                $validator = Validator::make(
                    $data,
                    $this->itemRules($type)
                );
                if ($validator->fails()) {
                    $result = array(
                        'success' => false,
                        'errors' => $validator->messages()->toArray()
                    );
                    return response()->json($result);
                }

                $tempMenuItem = new stdClass();
                //$tempMenuItem->url = $data['url'];
                $tempMenuItem->target = null;
                $tempMenuItem->active = true;
                $tempMenuItem->big_menu_id = !empty($data['big_menu_id']) ? $data['big_menu_id'] : null;
                $tempMenuItem->id = 'new_'.rand(0, 3000000);
                $tempMenuItem->bigMenu = null;
                $tempMenuItem->entry = null;
                $tempMenuItem->entry_id = null;
                $tempMenuItem->languages = array();
                $tempMenuItem->type = 'link';
                foreach ($data['title'] as $lang => $value) {
                    $itemLang = new stdClass();
                    $itemLang->language_id = $lang;
                    $itemLang->title = $value;
                    $itemLang->url = $data['url'][$lang];
                    $tempMenuItem->languages[] = $itemLang;

                    if ($lang == $defaultLanguage) {
                        $tempMenuItem->title = $value;
                    }
                }

                $viewHtml = view('admin.pages.menus.menu_item')
                    ->with('menuItem', $tempMenuItem)
                    ->render();
                $result = array(
                    'success' => true,
                    'menu_item_html' => $viewHtml
                );

                return response()->json($result);
            }
        }
    }

    private function buildStructure(&$menuStructure, &$i, &$data, &$website, $parentId = null)
    {
        $website = Localization::getWebsite();
        foreach ($menuStructure as $menuItem) {
            $i++;
            $menuItem->title = $data['titles'][$menuItem->id]['en'];
            $menuItem->position = $i;
            $menuItem->parent_id = $parentId;

            $menuItem->target = isset($data['new_windows'][$menuItem->id]) ? '_blank' : null;
            $menuItem->active = isset($data['states'][$menuItem->id]) ? true : false;
            $menuItem->use_object_title = isset($data['use_object_title'][$menuItem->id]) ? true : false;
            $menuItem->bigMenu = null;
            $menuItem->entry = null;
            $menuItem->websiteObject = null;
            $menuItem->object = null;

            $objectWO = null;
            if ($data['types'][$menuItem->id] == 'object') {
                $objectWO = WebsiteObject::where('website_object_id', $data['website_object_id'][$menuItem->id])
                    ->withTrashed()
                    ->where('website_id', $website->id)
                    ->first();
                $menuItem->websiteObject = $objectWO;
                $menuItem->object = $objectWO->objectable()->withTrashed()->first();
                $menuItem->type = 'object';
            } else if ($data['types'][$menuItem->id] == 'page') {
                $page = Entry::withTrashed()->where('id', $data['entry_id'][$menuItem->id])->first();
                if (!$page) {
                    //Todo: some error action?
                }
                $menuItem->entry = $page;
                $objectWO = WebsiteObject::withTrashed()->where('website_id', 1)->where('object_id', $page->id)->where('object_type', 'Entry')->first(); // $menuItem->entry->websites->findByWebsite($website->id);
                $menuItem->type = 'page';
            } else if ($data['types'][$menuItem->id] == 'content') {
                $menuItem->bigMenu = BigMenu::full()->find($data['big_menu_id'][$menuItem->id]);
                $menuItem->type = 'content';
            } else {
                $menuItem->type = 'link';
            }

            $menuItem->languages = array();
            foreach ($website->languages as $language) {
                $itemLang = new stdClass();
                $itemLang->language_id = $language->id;
                $itemLang->title = $data['titles'][$menuItem->id][$language->id];

                $itemLang->url = $data['urls'][$menuItem->id][$language->id];
                if ($objectWO) {
                    $pageWOLang = $objectWO->languages->findByLocale($language->id);
                    $itemLang->url = $pageWOLang->lang_uri;
                } else {
                    $itemLang->url = $data['urls'][$menuItem->id][$language->id];
                }
                $menuItem->languages[] = $itemLang;

                if ($language->id == Localization::getDefaultLocale()) {
                    $menuItem->title = $data['titles'][$menuItem->id][$language->id];
                }
            }

            //$i++;
            if (isset($menuItem->children)) {
                $this->buildStructure($menuItem->children, $i, $data, $website, $menuItem->id);
            }
        }
    }

    public function postEdit($menuId)
    {
        $website = Localization::getWebsite();
        $menu = Menu::find($menuId);
        if (!$menu || $menu->website_id != $website->id) {
            abort(404);
        }
        $user = Auth::guard('admin')->user();

        if (!$user->hasPermission('backend.menus.create')) {
            abort(403);
        }

        $ids = request()->input('menu_id');
        $ids = $ids ? $ids : array();
        $menuStructure = json_decode(request()->input('menu_structure'));
        $types = request()->input('menu_type');
        $titles = request()->input('title');
        $urls = request()->input('url');
        $states = request()->input('active');
        $newWindows = request()->input('new_window');
        $entriesIds = request()->input('entry_id');
        $objectIds = request()->input('website_object_id');
        $bigMenusIds = request()->input('big_menu_id');
        $toDelete = request()->input('to_delete');
        $contentType = ContentTypes::find('page');
        $useObjectTitle = request()->input('use_object_title');
        $pages = $contentType->toList();

        $data = array(
            'titles' => $titles,
            'types' => $types,
            'urls' => $urls,
            'states' => $states,
            'new_windows' => $newWindows,
            'entry_id' => $entriesIds,
            'website_object_id' => $objectIds,
            'big_menu_id' => $bigMenusIds,
            'use_object_title' => $useObjectTitle
        );
        $counter = 0;
        $this->buildStructure($menuStructure, $counter, $data, $website);

        //Validation
        $menuErrors = array();
        foreach ($ids as $itemId) {
            //validation fields
            $itemValidationFields = array(
                'title['.$itemId.']' => $titles[$itemId]
            );
            if ($types[$itemId] == 'link') {
                $itemValidationFields['url['.$itemId.']'] = $urls[$itemId];
            }
            if ($types[$itemId] == 'content') {
                $itemValidationFields['big_menu_id['.$itemId.']'] = $bigMenusIds[$itemId];
            }

            $validator = Validator::make(
                $itemValidationFields,
                $this->itemRules($types[$itemId], $itemId)
            );

            if ($validator->fails()) {
                $menuErrors[$itemId] = $validator->errors();
            }
        }
        $bigMenus = BigMenu::full()->get();
        if (sizeof($menuErrors) > 0) {
            return view('admin/pages/menus/edit_menu')
                ->with(array(
                    'menu' => $menu,
                    'pages' => $pages,
                    'menuItems' => $menuStructure,
                    'menu_errors' => $menuErrors,
                    'to_delete' => $toDelete,
                    'bigMenus' => $bigMenus,
                    'objectTypes' => \App\Libs\Backoffice\Generic\Fields\LinkField::OBJECT_TYPES,
                    "searchUrl" => url("admin/content/auto-complete"),
                ));
        }

        //Saves Menu
        DB::transaction(function () use ($menu, $menuStructure, $toDelete) {
            $this->saveMenuStructure($menu->id, $menuStructure);

            //deletes excluded menu items
            if ($toDelete) {
                $toDelete = explode(',', $toDelete);
                foreach ($toDelete as $id) {
                    if (is_numeric($id)) {
                        $menu->menuItems()->find($id)->delete();
                    }
                }
            }
        });

        $menu->resetCache();

        return redirect()->to('/admin/menu/edit/'.$menuId)->with("message", trans('backend.save_success'));
    }

    private function saveMenuStructure($menuId, &$menuStructure, $parentId = null)
    {
        $website = Localization::getWebsite();

        foreach ($menuStructure as $item) {
            if (strpos($item->id, 'new_') !== false) {
                //New MenuITem
                $menuItem = new MenuItem();
            } else {
                //Existing MenuItem
                $menuItem = MenuItem::find($item->id);
                //Reset langugage fields
                MenuItemLanguage::where('menu_item_id', $item->id)->delete();
            }
            $menuItem->parent_id = $parentId;
            $menuItem->menu_id = $menuId;
            $menuItem->target = $item->target;
            $menuItem->position = $item->position;
            $menuItem->active = $item->active;
            $menuItem->use_object_title = $item->use_object_title;

            //Language fields
            $langFields = array();
            foreach ($item->languages as $language) {
                $menuItemLang = new MenuItemLanguage(array(
                    'language_id' => $language->language_id,
                    'title' => $language->title
                ));
                if (isset($item->websiteObject) && $item->websiteObject) {
                    //Object item
                    $menuItem->website_object_id = $item->websiteObject->website_object_id;
                    $woLang = $item->websiteObject->languages->findByLocale($language->language_id);
                    $menuItemLang->url = $woLang->lang_uri;
                }
                if (isset($item->entry) && $item->entry) {
                    //Page item
                    $menuItem->entry_id = $item->entry->id;
                    $entryWO = $item->entry->websites->findByWebsite($website->id);
                    $entryWOLang = $entryWO->languages->findByLocale($language->language_id);
                    $menuItemLang->url = $entryWOLang->lang_uri;
                } else {
                    //Link Item

                    $menuItemLang->url = $language->url;
                }
                $langFields[] = $menuItemLang;
            }
            if (isset($item->bigMenu) && $item->bigMenu) {
                $menuItem->big_menu_id = $item->bigMenu->id;
            }

            $menuItem->save();
            $menuItem->languages()->saveMany($langFields);

            if (isset($item->children)) {
                $this->saveMenuStructure($menuId, $item->children, $menuItem->id);
            }
        }
    }

    public function getEdit($menuId = null)
    {
        if ($menuId == null && !is_numeric($menuId)) {
            abort(404);
        }
        $user = Auth::guard('admin')->user();
        $website = Localization::getWebsite();
        $menu = Menu::find($menuId);
        if (!$menu || $menu->website_id != $website->id) {
            abort(404);
        }
        if (!$user->hasPermission('backend.menus.view')) {
            abort(403);
        }

        RequestContext::set('selected_menu', 'admin_menus');
        RequestContext::set('selected_menu_option', 'admin_menu_'.$menu->id);

        $contentType = ContentTypes::find('page');
        $pages = $contentType->toList();

        $structuredMenu = $menu->getStructuredItems();

        $bigMenus = BigMenu::full()->get();

        return view('admin/pages/menus/edit_menu')
            ->with(array(
                'user' => $user,
                'menu' => $menu,
                'pages' => $pages,
                'menuItems' => $structuredMenu,
                'bigMenus' => $bigMenus,
                'objectTypes' => \App\Libs\Backoffice\Generic\Fields\LinkField::OBJECT_TYPES,
                "searchUrl" => url("admin/content/auto-complete"),
            ));
    }

    private function itemRules($type, $groupIndex = null)
    {
        $website = Localization::getWebsite();
        $languages = $website->languages;
        if ($groupIndex) {
            $groupIndex = '['.$groupIndex.']';
        }
        if ($type == 'link') {
            $rules = generateLangRules(array(
                'title'.$groupIndex => 'required|max:100',
                'url'.$groupIndex => 'required|max:255'
            ), $languages);
        } else if ($type == 'content') {
            $rules = generateLangRules(array(
                'title'.$groupIndex => 'required|max:100',
                'url'.$groupIndex => 'max:255'
            ), $languages);
            $rules['big_menu_id'.$groupIndex] = 'required|integer';
        } else {
            $rules = generateLangRules(array(
                'title'.$groupIndex => 'required|max:100',
            ), $languages);
        }
        return $rules;
    }
}
