<?php 

use Eae\Backoffice\Grid as EaeGrid;
use Eae\Backoffice\Generic\ContentType;
use Eae\Support\Contracts\SavableFieldInterface;
use Eae\Support\Contracts\ExternalFieldInterface;
use Eae\Backoffice\Generic\Fields\MediaPickerField;

class AdminContentController extends Controller { 
    
    public function __construct(){
        $this->beforeFilter('csrf', array('on' => array('post', 'delete'))); 
    }
    
    
    public function getIndex($type){
        $contentType = ContentTypes::find($type);

        $user = Auth::backend()->user();
        if(!$user->hasPermission("cms.manage")){
            App::abort(403, Lang::get("http_status.403"));    
        }
        
        return View::make('admin/generic/pages/list', array("contentType" => $contentType));
    }
    
    public function postList($type){
        $contentType = ContentTypes::find($type);
        
        $user = Auth::backend()->user();
        
        if(!$user->hasPermission("cms.manage")){
            App::abort(403, Lang::get("http_status.403"));    
        }
        
        $page = Input::get("current");
        $sort = Input::get("sort");
        $search = Input::get("searchPhrase");
        $rowCount = Input::get("rowCount");
        
        if(empty($sort) && $contentType->isOrderable() && !$contentType->isHierarchic()){
            $sort = array("position" => "asc");    
        }
        $list = $contentType->toList($page, $rowCount, $sort, $search);

        return Response::json($list);
    }
    
    public function postCheckSlug(){
        $originSlug = Input::get("slug");
        $langId = Input::get("lang");
        
        if(empty($originSlug) || empty($langId)){
            return Response::json(array(
                "error" => "bad_syntax",
                "description" => "The request is missing the slug"
            ), 400);
        }
        $slug = $this->_generateSlug($originSlug, $langId);
       
        if($slug === false){
            return Response::json(array(
                "error" => "invalid",
                "description" => "Impossible to generate this slug"
            ), 400);        
        }else{
            return Response::json(array("slug" => $slug));
        }
    }
    
    private function _generateSlug($originSlug, $langId){
        $originSlug = urlize($originSlug);
        $slug = $originSlug;
        
        $slugCounter = 1;
        while(WebsiteObject::hasSlug($slug, $langId) && $slugCounter <= 100){
            $slug = $originSlug . "-" . $slugCounter;
            $slugCounter++;   
        }
        
        if($slugCounter == 100){
            return false;
        }else{
            return $slug;
        }    
    }
    
    public function getFormTemplate($type, $parentId){
        if(!is_numeric($parentId)){
            App::abort(404);
        }
        
        $contentType = ContentTypes::find($type); 
        
        if(!$contentType->userHasPermission()){
            App::abort(403, Lang::get("http_status.403"));    
        }  
        
        $parentData = $contentType->getParent();
        
        if(empty($parentData)){
            App::abort(404, Lang::get("http_status.404"));    
        }
        $modelType = $contentType->getModelType();
        $model = $modelType::where($parentData["field"], $parentId)->first();
        
        if(empty($model)){
            $model = $this->_insertFormTemplate($contentType,$parentId);
        }
        $url = "/admin/content/form/{$type}/{$model->id}/{$parentId}";
        
        
        return Redirect::to($url);  
    }
    
    private function _insertFormTemplate($contentType, $parentId){
        $loggedUser = Auth::backend()->user();
        $modelType = $contentType->getModelType();
        $model = new $modelType;
        
        $parentData = $contentType->getParent();
        $parentContentType = ContentTypes::find($parentData["contentType"]);
        $parentModelType = $parentContentType->getModelType();
        $parentModel = $parentModelType::find($parentId);
        $fkName = $parentModel->getForeignKey();
        
        if(empty($parentModel)){
            App::abort(404);    
        }
        DB::beginTransaction();
       
        try{
            $model->$fkName = $parentId;
            $model->backend_user_id = $loggedUser->id; 
            $model->save();
              
            $languageModels = $model->languages;
            $languageModelType = $model->languages()->getRelated();
            
            foreach($parentModel->languages as $parentLangModel){
                $languageModel = new $languageModelType; 
                $languageModel->language_id = $parentLangModel->language_id; 
                $languageModel->title = $parentLangModel->title;   
                $languageModels->add($languageModel);
            }
            
            $model->languages()->saveMany($languageModels->all());
            
            $websiteObjects = $model->websites;
            $parentWebsiteObject = $parentModel->websites->first();

            $websiteObject = new WebsiteObject;
            $websiteObject->content_type = $contentType->getType();

            $slug = $parentWebsiteObject->slug . "-conf-" . $parentWebsiteObject->id;
            $websiteObject->slug = $slug;
            $websiteObject->status = $parentWebsiteObject->status;
            $websiteObjects->add($websiteObject);
            
            $model->websites()->saveMany($websiteObjects->all());
            
            foreach ($parentModel->languages as $langModel) {
                $woLang = new WebsiteObjectLanguage ();
                $woLang->website_object_id = $websiteObject->id;
                $woLang->wo_language_id = $langModel->language_id;
                $woLang->lang_slug = $slug;
                $woLang->lang_uri = null; 
                
                $woLang->save(); 
            }
            
            DB::commit();
        }catch(Exception $e){
            DB::rollback();
            Log::error($e);
            throw($e);
        }

        return $model;        
    }
    
    public function getForm($type, $id = false, $parentId = false, $parentContentType = false, $parentFieldName = false){
 
        $contentType = ContentTypes::find($type);
                   
        if(!$contentType->userHasPermission()){
            App::abort(403, Lang::get("http_status.403"));    
        }
        
        $parentData = $contentType->getParent();
        //var_dump($parentData); die;
        if ($parentContentType && $parentFieldName) {
            $parentType = ContentTypes::find($parentContentType);
            $parentField = $parentType->getFields()->find($parentFieldName);
            if (!$parentField || $parentField->getObjectType() != $type) {
                App::abort(404);
            } 
            
            $parentData = array(
                'field' => $parentFieldName,
                'contentType' => $parentContentType
            );
        }
        
        $modelType = $contentType->getModelType();
        
        if(!empty($id)){
            if(!is_numeric($id)){
                App::abort(404);
            }

            $model = $modelType::find($id);
            
            if(empty($model)){
                App::abort(404);    
            }
            
        }else{
            if(!$contentType->userHasPermission()){
                App::abort(403, Lang::get("http_status.403"));    
            }

            $modelType = $contentType->getModelType();
            $model = new $modelType;    
        }
        if(!$model->exists && (!empty($parentId) && empty($parentData)) || 
            (empty($parentId) && !empty($parentData))){
             App::abort(400, Lang::get("http_status.400"));    
        } 
        
        if(Request::ajax()){
            return View::make('admin/generic/components/form', 
                array(
                    "model" => $model, 
                    "contentType" => $contentType, 
                    "parentId" => $parentId));
        }else{
            return View::make('admin/generic/pages/form', 
                array(
                    "model" => $model, 
                    "contentType" => $contentType, 
                    "parentId" => $parentId));    
        }
        
               
    }
    
    /**
    * Util to reconstruct all uris for a given content type
    *     
    * @param mixed $type
    */
    public function getUpdateUris ($type) {
        $contentType = ContentTypes::find($type); 
        
        if (!$contentType->userHasPermission()) {
            App::abort(403, Lang::get("http_status.403"));    
        }                                                
        
        if (!$contentType->getBaseUri()) {
            App::abort(500, "No base URI configured for this content type"); 
        }
        
        $modelType = $contentType->getModelType();
        $models = $modelType::full()->get();
        
        foreach ($models as $model) {
            $websiteObjects = $model->websites;
            $websiteObject = $websiteObjects->findByWebsite($website->id);
            $this->_updateUri($websiteObject, $contentType);
        }
        
        echo 'Success!';
    }
    private function _updateUri ($websiteObject, $contentType, $save = true) {
        $uri = $contentType->getBaseUri();  
        $languages = getAvailableLanguages();
        $defaultLang = getDefaultLanguage();
        
        $defaultUri = "";    
        if ($websiteObject->parent) {
            $parent = $websiteObject->parent;
            
            foreach ($languages as $langCode => $lang) {
                $parentWoLang = $parent->languages->findByLocale($langCode);
                $woLang = $websiteObject->languages->findByLocale($langCode);
                $woLang->lang_uri = $parentWoLang->lang_uri . '/' . $woLang->lang_slug;   
                if ($defaultLang == $langCode) {
                    $defaultUri = $woLang->lang_uri;   
                }
                if ($save) {
                    $woLang->save();
                }
            } 
        } else {   
            if ($websiteObject->slug == 'home') {
                $defaultUri = '/';
                foreach ($languages as $langCode => $lang) {
                    $woLang = $websiteObject->languages->findByLocale($langCode);
                    $woLang->lang_uri = $defaultUri;
                    if ($save) {
                        $woLang->save();
                    }
                } 
            } else { 
                  foreach ($languages as $langCode => $lang) {
                      $woLang = $websiteObject->languages->findByLocale($langCode);

                      if (is_array($uri)) {
                          $uriLang = $uri[$langCode];    
                      } else {
                          $uriLang = $uri;
                      }
                      $woLang->lang_uri = $uriLang . '/' . $woLang->lang_slug;
                      if ($defaultLang == $langCode) {
                          $defaultUri = $woLang->lang_uri;   
                      }
                      if ($save) {
                          $woLang->save();
                      }
                  }  
            }
        }
        $websiteObject->uri = $defaultUri;
        if ($save) {
            $websiteObject->save();
        }
        
        if ($websiteObject->website_object_id) {
            $children = $websiteObject->children;
            foreach ($children as $child) {
                $this->_updateUri($child, $contentType, $save);
            }
        }
    }
    
    public function postForm($type, $id = false, $parentId = false, $parentContentType = false, $parentFieldName = false){
        $contentType = ContentTypes::find($type); 
        
        if(!$contentType->userHasPermission()){
            App::abort(403, Lang::get("http_status.403"));    
        }
        
        $loggedUser = Auth::backend()->user();
        if(!empty($id)){
            if(!is_numeric($id)){
                App::abort(404);
            }
            
            $modelType = $contentType->getModelType();
            $model = $modelType::find($id);
            
            if(empty($model)){
                App::abort(404);    
            }
        }else{
            $modelType = $contentType->getModelType();
            $model = new $modelType;
        }
       
        $parentData = $contentType->getParent();
        $hasPivot = false;
        
        if ($parentContentType && $parentFieldName) {
            $parentType = ContentTypes::find($parentContentType);
            $parentField = $parentType->getFields()->find($parentFieldName);
            if (!$parentField || $parentField->getObjectType() != $type) {
                App::abort(404);
            } 
            
            $parentData = array(
                'field' => $parentFieldName,
                'contentType' => $parentContentType
            );
            $hasPivot = true;
        }
        
        if(!$model->exists && (!empty($parentId) && empty($parentData)) || 
            (empty($parentId) && !empty($parentData))){
             App::abort(400, Lang::get("http_status.400"));    
        }   
    
        $validation = $contentType->getValidation(!$model->exists);

        $validator = Validator::make(
            $validation["values"],
            $validation["rules"]
                   
        );

        $validator->setAttributeNames($validation["labels"]);
          
        $languages = getAvailableLanguages();
        foreach ($languages as $langCode => $lang) { 
            $originSlug = $validation["values"]["lang_slug"][$langCode];
            if ($model->exists && $model->website_object_id) {
                $woLang = WebsiteObjectLanguage::where('website_object_id', $model->website_object_id)
                    ->where('wo_language_id', $langCode)
                    ->first();
                if ($woLang && $woLang->lang_slug == $originSlug) {
                    continue;
                }
            }   
            $slug = $this->_generateSlug($originSlug, $langCode);
            $validation["values"]["lang_slug"][$langCode] = ($slug ? $slug : '');
        }
         
        if ($validator->fails()){
            
            Input::flash();
            RequestContext::set("errors", $validator->getMessageBag());
            View::share("errors", $validator->getMessageBag());
                
            if(Request::ajax()){
                return View::make('admin/generic/components/form', 
                    array(
                        "model" => $model, 
                        "contentType" => $contentType,
                        "parentId" => $parentId));    
            }else{
                return View::make('admin/generic/pages/form', 
                    array(
                        "model" => $model, 
                        "contentType" => $contentType,
                        "parentId" => $parentId));
            }
        }
        
        if(!empty($parentData) && !$model->exists && !$hasPivot){
            $parentField = $parentData["field"];
            $model->$parentField = $parentId;         
        }
        
        $modelFields = $contentType->getFields()->getSingleLanguageFields();
        
        foreach($modelFields as $field){
            if($field->isRelationField() || $field instanceof ExternalFieldInterface){
                continue;
            }
            $fieldName = $field->getName();
            if($field instanceof SavableFieldInterface){
                $field->save($model, $validation["values"][$fieldName]);  
            }else{
                $model->$fieldName = $validation["values"][$fieldName];    
            }   
        }
 
        DB::beginTransaction();
              
        try{
            if(!$model->exists){
                $model->backend_user_id = $loggedUser->id;
            }
            if ($model->exists || !$hasPivot) {
                $model->save();
            } else {
                $parentContentType = ContentTypes::find($parentData["contentType"]);
                $parentModelType = $parentContentType->getModelType();
                $parentModel = $parentModelType::find($parentId);
                $parentModel->$parentData["field"]()->save($model);
            }
            
            $languageFields = $contentType->getFields()->getMultiLanguageFields();
            $languageModels = $model->languages;
            
            foreach($languageFields as $field){  
                if($field->isRelationField() || $field instanceof ExternalFieldInterface){
                    continue;
                }
                
                $fieldName = $field->getName();
                $values = $validation["values"][$fieldName];
                $languageModelType = $model->languages()->getRelated();
                
                foreach($values as $languageId => $value){
                    $languageModel = $languageModels->findByLocale($languageId);
                    if(empty($languageModel)){
                        $languageModel = new $languageModelType; 
                        $languageModel->language_id = $languageId;   
                        $languageModels->add($languageModel);
                    }
                   
                    if($field instanceof SavableFieldInterface){
                        $field->save($languageModel, $value);  
                    }else{
                        $languageModel->$fieldName = $value;    
                    }

                }    
            }

            $model->languages()->saveMany($languageModels->all());
            $websiteObjects = $model->websites;
            
            $websiteObject = $websiteObjects->first();
            
            if (empty($websiteObject)) {
                $websiteObject = new WebsiteObject;
                $websiteObject->content_type = $contentType->getType();

                if($contentType->isOrderable()){
                    $position = WebsiteObject::maxPosition(
                        class_basename($model));
                    if(empty($position)){
                        $position = 0;    
                    }
                    $websiteObject->position = $position + 1;    
                }
                
                $websiteObjects->add($websiteObject);
                foreach ($languageModels as $lang) {
                    $woLang = new WebsiteObjectLanguage();   
                    $woLang->wo_language_id = $lang->language_id;
                    
                    $websiteObject->languages->add($woLang);
                }       
            }

            $defaultLang = getDefaultLanguage();
            foreach ($languageModels as $lang) {
                $woLang = $websiteObject->languages->findByLocale($lang->language_id);
                if (isset($validation["values"]["lang_slug"][$lang->language_id])) {
                    $woLang->lang_slug = $validation["values"]["lang_slug"][$lang->language_id];    
                } else {
                    $woLang->lang_slug = $validation["values"]["lang_slug"][$defaultLang];
                }
               
                if ($defaultLang == $lang->language_id) {
                    $websiteObject->slug = $validation["values"]["lang_slug"][$lang->language_id]; 
                }
            }
            $websiteObject->status = $validation["values"]["status"];
            $websiteObject->template = $validation["values"]["template"];
            
            if ($contentType->hasTemplate() || 
                $contentType->getBaseUri() != false) { 
                $this->_updateUri($websiteObject, $contentType, false);
            }

            $model->websites()->saveMany($websiteObjects->all());
            
            foreach ($websiteObjects as $websiteObject) {
                $websiteObject->languages()->saveMany($websiteObject->languages->all());
            }
            
            if($contentType->isSearchable()){ 
                $searchContents = $contentType->getSearchStructure($model);

                foreach($websiteObjects as $websiteObject){
                    $websiteObject->searches()->delete();
                    if ($websiteObject->status == 'draft') {
                        continue;
                    }                                       
                    
                    if(isset($searchContents)){ 
                        foreach($searchContents as $locale => $searchContent){
                            $search = new WebsiteObjectSearch($searchContent);
                            $search->language_id = $locale;
                            $websiteObject->searches()->save($search);           
                        }   
                    }      
                }
            }else{ 
                $websiteObject->searches()->delete();        
            }

            $relationFields = $contentType->getFields()->getRelationFields();
            
            foreach($relationFields as $field){
                $fieldName = $field->getName();
                if(isset($validation["values"][$fieldName])){
                    $field->save($model, $validation["values"][$fieldName]);   
                }
            }
            
            DB::commit();
        }catch(Exception $e){
            DB::rollback();
            Log::error($e);
            throw($e);
        }
        
        $redirectUrl = Request::path();
        if($id === false){
            $redirectUrl .= "/" . $model->id;    
        }
        Session::forget("_old_input");
        if(Request::ajax()){
            return Response::json(array(
                "id" => $model->id,
                "title" => $model->title,
                "website_object_id" => $model->website_object_id
            ));    
        }else{
            //If has template and has template configuration, jumps to it
            
            if ($contentType->hasTemplate()) {
                $objectTemplate = $contentType->getTemplates()[$websiteObject->template];
                if (isset($objectTemplate['contentType'])) {
                    $contentType = ContentTypes::find($objectTemplate['contentType']); 
                    $parentData = $contentType->getParent();
                    if(empty($parentData)){
                        App::abort(404, Lang::get("http_status.404"));    
                    }   
                    $modelType = $contentType->getModelType();
                    $configModel = $modelType::where($parentData["field"], $model->id)->first();
            
                    if (!$configModel) {
                        $redirectUrl = 'admin/content/form-template/' . $objectTemplate['contentType'] . '/' . $model->id;
                        return Redirect::to($redirectUrl); 
                    }  
                } 
            } 
            return Redirect::to($redirectUrl)->withMessage(Lang::get("backend.save_success"));    
        }    
    }
    
    public function deleteIndex(){
        $type = Input::get("type");
        $id = Input::get("id");
        $fullDelete = Input::get("fullDelete", false);
        
        if(empty($type) || empty($id) || !is_numeric($id)){
            return Response::json(array(
                "error" => "bad_syntax",
                "description" => Lang::get("http_status.400")),
                400);    
        }
        
        $contentType = ContentTypes::find($type);
        
        if(!$contentType->userHasPermission()){
            App::abort(403, Lang::get("http_status.403"));    
        }
        
        $modelType = $contentType->getModelType();
        
        $model = $modelType::find($id);
        
        if(empty($model)){
            return Response::json(array(
                "error" => "not_found",
                "description" => Lang::get("http_status.404")),
                404);   
        }
        
        DB::beginTransaction();
       
        try{ 
            $model->delete();
            WebsiteObject::where("object_id", $id)
                    ->where("object_type", $modelType)
                    ->delete(); 
            $this->cleanWebsiteObjects();                
            $this->_cleanWebsiteObjectSearches();                 
            DB::commit();
        } catch (Exception $e) {
            DB::rollback(); 
            Log::error($e);
            App::abort(500);
        }
 
        return Response::json(array("success" => true));
    }
    
    /**
    * Cleans the website objects table for objects that got deleted by database
    * foreign key cascade deletes
    * 
    */
    protected function cleanWebsiteObjects() {
        $contentTypes = ContentTypes::all();
        
        foreach ($contentTypes as $contentType) {
            $modelType = $contentType->getModelType(); 
            $model = new $modelType();
            $table = $model->getTable();
            
            $toDelete = WebsiteObject::where('content_type', $contentType->getType())
                ->whereNotExists(function($query) use ($table) {
                    $query->select(DB::raw(1))
                        ->from($table)
                        ->whereRaw(WebsiteObject::getTableName() . ".object_id = {$table}.id");
            })->delete();  
        }
    }
    
    protected function _cleanWebsiteObjectSearches(){
        DB::table("website_objects_search")
            ->whereNotExists(function($query){
                $query->select(DB::raw(1))
                    ->from("website_objects")
                    ->whereRaw("website_objects_search.website_object_id = website_objects.website_object_id");    
            })->delete();
    }
    
    public function getOrder ($type) {
        $contentType = ContentTypes::find($type);
        
        if(!$contentType->userHasPermission()){
            App::abort(403, Lang::get("http_status.403"));    
        }
        
        if ($contentType->isHierarchic()) {
            $entries = $contentType->toStructuredList();
        } else {
            $entries = $contentType->toList(null, null, array('position' => 'asc'))->all();
        }
        
        return View::make('admin/generic/pages/order', array(
            "contentType" => $contentType,
            "entries"     => $entries 
        ));
    }
    
    public function postOrder ($type) {
        $contentType = ContentTypes::find($type);
        
  
        if(!$contentType->userHasPermission()){
            App::abort(403, Lang::get("http_status.403"));    
        }
        
        $modelType = $contentType->getModelType();
        
        $newOrder = Input::get('content_order');
        $newOrder = json_decode($newOrder);
        
        if (!$newOrder || !is_array($newOrder)) {
            App::abort(400); 
        }
        
        DB::beginTransaction();
        try {
            $counter = 0;
            $this->_saveOrder($newOrder, $contentType->getModelType(), $counter);
            DB::commit();
        } catch (Exception $e) {
            DB::rollback();
            Log::error($e);
            App::abort(500);
        } 
  
        $redirectUrl = 'admin/content/index/' . $type;
        if(Request::ajax()){
            return Response::json(array("message" => "OK"));            
        }else{
            return Redirect::to($redirectUrl)->withMessage(Lang::get("backend.save_success"));     
        }
        
    }
    
    private function _saveOrder($orderTree, $objectType, &$i, $parent = null) {
        foreach ($orderTree as $orderItem) {
            $i++;
            if (!is_numeric($orderItem->id)) {
                App::abort(400);   
            }
            $websiteObject = WebsiteObject::find($orderItem->id);
            if (empty($websiteObject) || $websiteObject->object_type !== $objectType) {
                App::abort(400);
            }
            $websiteObject->position = $i;
            if ($parent) {
                $websiteObject->parent_id = $parent->id;
                if ($websiteObject->object_type == 'Entry') {
                    $websiteObject->uri = $websiteObject->parent->uri . '/' . $websiteObject->slug;
                }
            } else {
                if ($websiteObject->object_type == 'Entry') {
                    $websiteObject->uri = '/' . ($websiteObject->slug == 'home' ? '' : $websiteObject->slug);
                }
                $websiteObject->parent_id = null;
            }
            $websiteObject->save();
            
            if (isset($orderItem->children)) {
                $this->_saveOrder($orderItem->children, $objectType, $i, $orderItem);
            }
        }
    }
    
    public function postAutoComplete($type){
        $contentType = ContentTypes::find($type);

        $user = Auth::backend()->user();
        if(!$user->hasPermission("cms.manage")){
            App::abort(403, Lang::get("http_status.403"));    
        } 
        
        $searchTerm =  Input::get('searchTerm', '');
        $cleanedSearchTerm  = Formatter::transformItem($searchTerm, "strip_tags|xss_clean|trim");
           
        if(empty($cleanedSearchTerm)){
            return Response::json(array(
                "error" => Config::get("error.not_found"),
                "description" => Lang::get("response.not_found")
            ),404);    
        }
        
        
        $results = $contentType->autoComplete($cleanedSearchTerm);
        
        return Response::json($results,200); 
         
    }
}