<?php
    use Carbon\Carbon;
    class ImportController extends Controller
    {
        private $valuesForInsertion = [];
        private $valuesNotValidForInsertion = [];
        private $requiredFields = [];
        private $arrayKeys = [
            'title' => [
                'key' => 'titulo_do_artigo',
                'required' => true
            ],
            'occurrence_description' => [
                'key' => 'texto_de_apoio_superlead',
                'required' => false
            ],
            'locations' => [
                'key' => 'cidadevilaaldeia',
                'required' => true
            ],
            'personalities' => [
                'key' => 'personalidades',
                'required' => false
            ],
            'categories' => [
                'key' => 'area_politica_economia_sociedade_desporto_cultura_internacional',
                'required' => false
            ],
            'themes' => [
                'key' => 'tema_cheias_na_madeira_incendios_em_pedrogao_etc',
                'required' => false
            ],
            'keywords' => [
                'key' => 'palavras_chave',
                'required' => false
            ],
            'occurrence_audio' => [
                'key' => 'link_ficheiro_audio',
                'required' => false
            ],
            'occurrence_video' => [
                'key' => 'link_ficheiro_video',
                'required' => false
            ],
            'day' => [
                'key' => 'dia',
                'required' => true
            ],
            'month' => [
                'key' => 'mes',
                'required' => true
            ],
            'year' => [
                'key' => 'ano',
                'required' => true
            ]
        ];

        public function __construct()  {
            $this->requiredFields = array_filter($this->arrayKeys, function($field) {
                if($field['required']) {
                    return TRUE;
                }
                return FALSE;
            });
        }

        public function getIndex(){
            $this->_loadExcelFile();
            $this->_startImport();
            die("=== IMPORT CONTROLLER ===");
        }

        private function _loadExcelFile() {
            $path = Config::get("path.import.excel") . '/README.xlsx';
            Excel::filter('chunk')->load($path)->chunk(250, function($results)
            {
                foreach($results as $row)
                {
                    $item = $row->toArray(); // Get items
                    if($this->_isValueValidForInsertion($item)) {
                        $this->valuesForInsertion[] = $item;
                    } else {
                        $this->valuesNotValidForInsertion[] = $item;
                    }
                }
            });
        }

        private function _isValueValidForInsertion($item) {
            foreach($this->requiredFields as $key => $value) {
                $itemKey = $value["key"];
                if($this->_isEmpty($item[$itemKey])) {
                    return FALSE;
                }
            }
            return TRUE;
        }

        private function _isEmpty($value) {
            $valueToValidate = trim($value);
            if(empty($valueToValidate)) {
                return TRUE;
            }
            return FALSE;
        }

        private function _startImport() {
            if(sizeof($this->valuesForInsertion) <= 0) return;
            DB::beginTransaction();
            try {
                foreach($this->valuesForInsertion as $valueForInsertion) {
                    $importItem = $this->_importItem($valueForInsertion);
                    if(sizeof($importItem) > 0) {
                        $this->_createOccurrence($importItem);
                    }
                }
                DB::commit();
            } catch(Exception $e) {
                DB::rollback();
                throw($e);
            }
        }

        private function _importItem($item) {
            $finalItem = [];
            foreach($this->arrayKeys as $key => $value) {
                $itemKey = $value['key'];
                switch($key) {
                    case 'locations':
                        $finalItem[$key] = $this->_getLocation($item[$itemKey]);
                        break;
                    case 'personalities':
                        $finalItem[$key] = $this->_getPersonality($item[$itemKey]);
                        break;
                    case 'categories':
                        $finalItem[$key] = $this->_getCategory($item[$itemKey]);
                        break;
                    case 'themes':
                        $finalItem[$key] = $this->_getTheme($item[$itemKey]);
                        break;
                    case 'keywords':
                        $finalItem[$key] = $this->_getKeywords($item[$itemKey]);
                        break;
                    default:
                        $finalItem[$key] = $item[$itemKey];
                }
            }
            return $finalItem;
        }

        private function _createOccurrence($occurrence) {
            $slug = $this->_generateSlug('event_'.$occurrence['title']);
            $date = $this->_parseDate($occurrence);
            $dbOccurrence = new Occurrence();
            $dbOccurrence->occurrence_audio = $occurrence['occurrence_audio'];
            $dbOccurrence->occurrence_video = $occurrence['occurrence_video'];
            $dbOccurrence->occurrence_date = $date;
            $dbOccurrence->is_on_map = 1;
            $dbOccurrence->save();
            $dbOccurrence->locations()->attach($occurrence['locations']);
            if(sizeOf($occurrence['personalities']) > 0) {
                $dbOccurrence->personalities()->attach($occurrence['personalities']);
            }
            $dbOccurrence->categories()->attach($occurrence['categories']);
            $dbOccurrence->themes()->attach($occurrence['themes']);
            if(sizeOf($occurrence['keywords']) > 0) {
                $dbOccurrence->keywords()->attach($occurrence['keywords']);
            }

            $dbOccurrenceLang = new OccurrenceLanguage();
            $dbOccurrenceLang->occurrence_id = $dbOccurrence->id;
            $dbOccurrenceLang->language_id = 'en';
            $dbOccurrenceLang->title = $occurrence['title'];
            $dbOccurrenceLang->occurrence_description = $occurrence['occurrence_description'];
            $dbOccurrenceLang->save();

            $dbOccurrenceWebsiteObject = new WebsiteObject();
            $dbOccurrenceWebsiteObject->object_id = $dbOccurrence->id;
            $dbOccurrenceWebsiteObject->object_type = get_class($dbOccurrence);
            $dbOccurrenceWebsiteObject->content_type = "occurrences";
            $dbOccurrenceWebsiteObject->slug = $slug;
            $dbOccurrenceWebsiteObject->status = "published";
            $dbOccurrenceWebsiteObject->save();

            $dbOccurrenceWebsiteObjectLang = new WebsiteObjectLanguage();
            $dbOccurrenceWebsiteObjectLang->website_object_id = $dbOccurrenceWebsiteObject->id;
            $dbOccurrenceWebsiteObjectLang->wo_language_id = 'en';
            $dbOccurrenceWebsiteObjectLang->lang_slug = $slug;
            $dbOccurrenceWebsiteObjectLang->save();

            return $dbOccurrence->id;
        }

        private function _getLocation($location) {
            if($this->_isEmpty($location)) return NULL;
            $location = trim($location);
            $locationModel = Location::full()
                ->select('id')
                ->where('title', $location)
                ->first();

            if($locationModel) {
                return $locationModel->id;
            }

            return $this->_createLocation($location);
        }

        private function _createLocation($location) {
            $slug = $this->_generateSlug('location_'.Hash::make($location));
            $dbLocation = new Location();
            $dbLocation->save();

            $dbLocationLang = new LocationLanguage();
            $dbLocationLang->location_id = $dbLocation->id;
            $dbLocationLang->language_id = 'en';
            $dbLocationLang->title = $location;
            $dbLocationLang->save();

            $dbLocationWebsiteObject = new WebsiteObject();
            $dbLocationWebsiteObject->object_id = $dbLocation->id;
            $dbLocationWebsiteObject->object_type = get_class($dbLocation);
            $dbLocationWebsiteObject->content_type = "locations";
            $dbLocationWebsiteObject->slug = $slug;
            $dbLocationWebsiteObject->status = "published";
            $dbLocationWebsiteObject->save();

            $dbLocationWebsiteObjectLang = new WebsiteObjectLanguage();
            $dbLocationWebsiteObjectLang->website_object_id = $dbLocationWebsiteObject->id;
            $dbLocationWebsiteObjectLang->wo_language_id = 'en';
            $dbLocationWebsiteObjectLang->lang_slug = $slug;
            $dbLocationWebsiteObjectLang->save();

            return $dbLocation->id;
        }

        private function _getPersonality($personalities) {
            $personalities = explode(";", $personalities);
            $finalPersonalities = [];
            foreach($personalities as $personality) {
                if($this->_isEmpty($personality)) break;
                $personality = trim($personality);
                $personalityModel = Personality::full()
                    ->select('id')
                    ->where('title', $personality)
                    ->first();

                if($personalityModel) {
                    $finalPersonalities[] = $personalityModel->id;
                } else {
                    $finalPersonalities[] = $this->_createPersonality($personality);
                }
            }
            return $finalPersonalities;
        }

        private function _createPersonality($personality) {
            $slug = $this->_generateSlug('personality_'.Hash::make($personality));
            $dbPersonality = new Personality();
            $dbPersonality->save();

            $dbPersonalityLang = new PersonalityLanguage();
            $dbPersonalityLang->personality_id = $dbPersonality->id;
            $dbPersonalityLang->language_id = 'en';
            $dbPersonalityLang->title = $personality;
            $dbPersonalityLang->save();

            $dbPersonalityWebsiteObject = new WebsiteObject();
            $dbPersonalityWebsiteObject->object_id = $dbPersonality->id;
            $dbPersonalityWebsiteObject->object_type = get_class($dbPersonality);
            $dbPersonalityWebsiteObject->content_type = "personalities";
            $dbPersonalityWebsiteObject->slug = $slug;
            $dbPersonalityWebsiteObject->status = "published";
            $dbPersonalityWebsiteObject->save();

            $dbPersonalityWebsiteObjectLang = new WebsiteObjectLanguage();
            $dbPersonalityWebsiteObjectLang->website_object_id = $dbPersonalityWebsiteObject->id;
            $dbPersonalityWebsiteObjectLang->wo_language_id = 'en';
            $dbPersonalityWebsiteObjectLang->lang_slug = $slug;
            $dbPersonalityWebsiteObjectLang->save();

            return $dbPersonality->id;
        }

        private function _getCategory($category) {
            if($this->_isEmpty($category)) return NULL;
            $category = trim($category);
            $categoryModel = Category::full()
                ->select('id')
                ->where('title', $category)
                ->first();

            if($categoryModel) {
                return $categoryModel->id;
            }

            return $this->_createCategory($category);
        }

        private function _createCategory($category) {
            $slug = $this->_generateSlug('category_'.Hash::make($category));
            $dbCategory = new Category();
            $dbCategory->save();

            $dbCategoryLang = new CategoryLanguage();
            $dbCategoryLang->category_id = $dbCategory->id;
            $dbCategoryLang->language_id = 'en';
            $dbCategoryLang->title = $category;
            $dbCategoryLang->save();

            $dbCategoryWebsiteObject = new WebsiteObject();
            $dbCategoryWebsiteObject->object_id = $dbCategory->id;
            $dbCategoryWebsiteObject->object_type = get_class($dbCategory);
            $dbCategoryWebsiteObject->content_type = "categories";
            $dbCategoryWebsiteObject->slug = $slug;
            $dbCategoryWebsiteObject->status = "published";
            $dbCategoryWebsiteObject->save();

            $dbCategoryWebsiteObjectLang = new WebsiteObjectLanguage();
            $dbCategoryWebsiteObjectLang->website_object_id = $dbCategoryWebsiteObject->id;
            $dbCategoryWebsiteObjectLang->wo_language_id = 'en';
            $dbCategoryWebsiteObjectLang->lang_slug = $slug;
            $dbCategoryWebsiteObjectLang->save();

            return $dbCategory->id;
        }

        private function _getTheme($theme) {
            if($this->_isEmpty($theme)) return NULL;
            $theme = trim($theme);
            $themeModel = Theme::full()
                ->select('id')
                ->where('title', $theme)
                ->first();

            if($themeModel) {
                return $themeModel->id;
            }

            return $this->_createTheme($theme);
        }

        private function _createTheme($theme) {
            $slug = $this->_generateSlug('theme_'.Hash::make($theme));
            $dbTheme = new Theme();
            $dbTheme->save();

            $dbThemeLang = new ThemeLanguage();
            $dbThemeLang->theme_id = $dbTheme->id;
            $dbThemeLang->language_id = 'en';
            $dbThemeLang->title = $theme;
            $dbThemeLang->save();

            $dbThemeWebsiteObject = new WebsiteObject();
            $dbThemeWebsiteObject->object_id = $dbTheme->id;
            $dbThemeWebsiteObject->object_type = get_class($dbTheme);
            $dbThemeWebsiteObject->content_type = "themes";
            $dbThemeWebsiteObject->slug = $slug;
            $dbThemeWebsiteObject->status = "published";
            $dbThemeWebsiteObject->save();

            $dbThemeWebsiteObjectLang = new WebsiteObjectLanguage();
            $dbThemeWebsiteObjectLang->website_object_id = $dbThemeWebsiteObject->id;
            $dbThemeWebsiteObjectLang->wo_language_id = 'en';
            $dbThemeWebsiteObjectLang->lang_slug = $slug;
            $dbThemeWebsiteObjectLang->save();

            return $dbTheme->id;
        }

        private function _getKeywords($keywords) {
            $keywords = explode(";", $keywords);
            $finalKeywords = [];
            foreach($keywords as $keyword) {
                if($this->_isEmpty($keyword)) break;
                $keyword = trim($keyword);
                $keywordModel = Keyword::full()
                    ->select('id')
                    ->where('title', $keyword)
                    ->first();

                if($keywordModel) {
                    $finalKeywords[] = $keywordModel->id;
                } else {
                    $finalKeywords[] = $this->_createKeyword($keyword);
                }
            }
            return $finalKeywords;
        }

        private function _createKeyword($keyword) {
            $slug = $this->_generateSlug('keyword_'.Hash::make($keyword));
            $dbKeyword = new Keyword();
            $dbKeyword->save();

            $dbKeywordLang = new KeywordLanguage();
            $dbKeywordLang->keyword_id = $dbKeyword->id;
            $dbKeywordLang->language_id = 'en';
            $dbKeywordLang->title = $keyword;
            $dbKeywordLang->save();

            $dbKeywordWebsiteObject = new WebsiteObject();
            $dbKeywordWebsiteObject->object_id = $dbKeyword->id;
            $dbKeywordWebsiteObject->object_type = get_class($dbKeyword);
            $dbKeywordWebsiteObject->content_type = "keywords";
            $dbKeywordWebsiteObject->slug = $slug;
            $dbKeywordWebsiteObject->status = "published";
            $dbKeywordWebsiteObject->save();

            $dbKeywordWebsiteObjectLang = new WebsiteObjectLanguage();
            $dbKeywordWebsiteObjectLang->website_object_id = $dbKeywordWebsiteObject->id;
            $dbKeywordWebsiteObjectLang->wo_language_id = 'en';
            $dbKeywordWebsiteObjectLang->lang_slug = $slug;
            $dbKeywordWebsiteObjectLang->save();

            return $dbKeyword->id;
        }

        private function _generateSlug($originSlug){
            $originSlug = urlize($originSlug);
            $slug = $originSlug;

            $slugCounter = 1;
            while(WebsiteObject::hasSlug($slug, 'en') && $slugCounter <= 100){
                $slug = $originSlug . "-" . $slugCounter;
                $slugCounter++;
            }

            if($slugCounter == 100){
                return false;
            }else{
                return $slug;
            }
        }

        private function _parseDate($occurrence) {
            $day = $occurrence['day'];
            $month = $this->_parseMonth($occurrence['month']);
            $year = $occurrence['year'];

            $date = Carbon::parse($day . ' ' . $month . ' ' . $year);

            return $date->format("Y-m-d");
        }

        private function _parseMonth($month) {
            $month = strtolower(trim($month));
            $months = [
                "janeiro" => "January",
                "fevereiro" => "February",
                "marco" => "March",
                "março" => "March",
                "abril" => "April",
                "maio" => "May",
                "junho" => "June",
                "julho" => "July",
                "agosto" => "August",
                "setembro" => "September",
                "outubro" => "October",
                "novembro" => "November",
                "dezembro" => "December"
            ];

            return $months[$month];
        }
    }
