<?php

namespace Support;

use App;
use Band;
use Carbon\Carbon;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Config;

class Contest {

    protected $edition = 'pt';
    protected $top_voted = false;

    //datas limites para votação de juri
    protected $deadlines = [
        'pt' => '11-12-2020 17:00:00',
        'pt-BR' => '11-12-2020 17:00:00',
        'es' => '11-12-2020 17:00:00'
    ];

    /**
     * Gets a contest option
     *
     * @param string $optionKey     Identifier for the option
     * @return string
     */
    public function getContestOption($optionKey) {
        $result = \ContestOption::where('option_key', '=', $optionKey)->first();
        return $result['option_value'];
    }

    /**
     * Gets contest options with multiple prefixes
     *
     * @param array $prefixes                   Prefix in the "option_key" column on the contest_options table
     * @param boolean $removePrefixFromResult   To remove or not to remove the prefix from the key on the results
     * @return array
     */
    public function getContestOptionsWithPrefixes($prefixes, $removePrefixFromResult = false) {
        $results = [];

        foreach($prefixes as $prefix) {
            $results = array_merge($results, $this->getContestOptionsWithPrefix($prefix, $removePrefixFromResult));
        }

        return $results;
    }

    /**
     * Gets contest options with a single prefix
     *
     * @param string $prefix                    Prefix in the "option_key" column on the contest_options table
     * @param boolean $removePrefixFromResult   To remove or not to remove the prefix from the key on the results
     * @return array
     */
    public function getContestOptionsWithPrefix($prefix, $removePrefixFromResult = true) {
        $dbResults = \ContestOption::where('option_key', 'like', "{$prefix}_%")->get()->toArray();

        $results = array_reduce($dbResults, function($finalResult, $data) use ($prefix, $removePrefixFromResult) {
            $option_key               = ($removePrefixFromResult) ? preg_replace("/^{$prefix}_/", '', $data['option_key']) : $data['option_key'];
            $finalResult[$option_key] = $data['option_value'];

            return $finalResult;
        }, []);

        return $results;
    }

    public function setEdition($edition) {
        $this->edition = $edition;
    }

    public function getEdition() {
        return $this->edition;
    }

    public function getRatingsDeadline() {

        return array_get($this->deadlines, $this->edition, $this->deadlines['pt']);
    }

    protected function times() {

        return $this->getContestOptionsWithPrefix('time');
    }

    protected function dates() {
        return $this->getContestOptionsWithPrefix('date');
    }

    public function timezone() {
        $zones = Config::get('contest.timezones');

        return array_get($zones, $this->edition, $zones['pt']);
    }

    public function getTime($date) {
        return array_get($this->times(), $date, '23:59:59');
    }

    public function getDate($date) {
        list($hour, $minute, $second) = explode(':', $this->getTime($date));

        $date = Carbon::parse(array_get($this->dates(), $date, date('Y-m-d')));

        $date->hour = $hour;
        $date->minute = $minute;
        $date->second = $second;

        return $date;
    }

    public function getDateTime($date) {

        $date = Carbon::parse(array_get($this->dates(), $date));


        return $date;
    }


    public function showShortPreSelectionButtonInJuriAdmin(){
        if (Contest::getDate('show-semi-finalists')->isPast()) {
            return false;
        }
        return true;
    }


    public function status() {

        if ($this->inTeaser()){
            return 'teaser';
        }

        if ($this->hasEnded()) {
            return 'end';
        }
        if ($this->getDate('semi-final')->isPast()) {
            return 'semi-final';
        }
        if ($this->getDate('semi-final-limbo')->isPast()) {
            return 'semi-final-limbo';
        }

        if ($this->getDate('vote')->isPast()) {
            return 'vote';
        }

        return 'participate';
    }

    public function inTeaser() {

        return $this->getDateTime('teaser')->isPast() &&  $this->getDateTime('end_teaser')->isFuture();
    }


    public function hasBegun() {

        return $this->getDate('participate')->isPast();
    }

    public function hasEnded() {
        return $this->getDate('end')->isPast();
    }

    public function openToVote() {
        return in_array($this->status(), ['participate', 'vote']);
    }

    public function votingHasClosed() {
        return !$this->openToVote();
    }

    public function displayDate($date, $format = null) {
        return Str::lower(display_date($date, is_null($format) ? '%e de %B' : $format));
    }

    public function displayDateStart($format = null) {
        return $this->displayDate($this->getDate('participate'), $format);
    }

    public function displayDateEndParticipate($format = null) {
        return $this->displayDate($this->getDate('vote'), $format);
    }

    public function displayDateEndVote($format = null) {
        return $this->displayDate($this->getDate('semi-final-limbo'), $format);
    }

    public function displayDateSemiFinal($format = null) {
        return $this->displayDate($this->getDate('show-semi-finalists'), $format);
    }

    public function displayDateEndSemiFinal($format = null) {
        return $this->displayDate($this->getDate('end'), $format);
    }

    public function displayDateShowFinalists($format = null) {
        return $this->displayDate($this->getDate('show-finalists'), $format);
    }

    public function displayDateFinal($format = null) {
        return $this->displayDate($this->getDate('final'), $format);
    }

    public function rulesUrl() {
        $rules = Config::get('contest.rules');

        return array_get($rules, $this->edition, $rules['pt']);
    }

    public function dataUrl() {
        $dataPolicyUrls = Config::get('contest.data-policy-url');

        return array_get($dataPolicyUrls, $this->edition, $dataPolicyUrls['pt']);
    }


    public function editionUrl($edition = null) {
        $environment = App::environment();
        $edition = $edition ?: $this->edition;
        $urls = Config::get('contest.edition-urls');
        return array_get($urls, "{$edition}.{$environment}", array_get($urls, "pt.{$environment}"));
    }

    public function editionUrls() {
        $environment = App::environment();
        $configUrls = Config::get('contest.edition-urls');
        $urls = [
            'active' => [],
            'inactive' =>[]
        ];
        foreach ($configUrls as $edition=>$environments){
            if(isset($environments[$environment])){
                if ($this->edition===$edition){
                    $urls['active'] = [
                        'name'=> $this->editionName(),
                        'country'=> $this->editionCountry($edition),
                        'link'=>$environments[$environment]
                    ];
                    continue;
                }
                $urls['inactive'][] = [
                    'name' => $this->editionName($edition),
                    'link' => $environments[$environment],
                    'country'=> $this->editionCountry($edition),
                ];
            }
        }
        return $urls;
    }



    public function institutionalUrl() {
        $urls = Config::get('contest.institucional-urls');

        return array_get($urls, $this->edition, $urls['pt']);
    }

    public function name() {
        $names = Config::get('contest.names');

        return array_get($names, $this->edition, $names['pt']);
    }

    public function editionName($currEdition = null) {
        if (empty($currEdition)){
            $currEdition = $this->edition;
        }
        $names = Config::get('contest.edition-names');

        return array_get($names, $currEdition, $names['pt']);
    }

    public function editionCountry($edition) {

        $countries = [
            'pt'=>'Portugal',
            'es'=>'España',
            'pt-BR'=>'Brasil',
        ];
        return isset($countries[$edition]) ? $countries[$edition] : 'Portugal';
    }



    public function title($title = null) {
        return (!is_null($title) ? "{$title} - " : '') . $this->name();
    }

    public function email() {

        $email = Config::get('contest.emails');
        return array_get($email, $this->edition, $email['pt']);
    }

    public function emailFrom() {

        $email = Config::get('mail.from.address');
        return $email;

    }

    public function smtpMailer() {
        $username = Config::get('contest.smtp-mailer-user');
        return array_get($username, $this->edition, $username['pt']);
    }

    public function language() {
        $language = [
            'pt' => 'pt_PT',
            'pt-BR' => 'pt_BR',
            'es' => 'es-ES',
        ];

        return array_get($language, $this->edition, $language['pt']);
    }

    public function facebookApp() {
        $credentials = Config::get('facebook.apps');
        return array_get($credentials, $this->edition, $credentials['pt']);
    }


    public function GtmId() {
        $id = [
            'pt' => 'GTM-PVG7833',
            'pt-BR' => 'GTM-K3BV62J',
            'es' => 'GTM-MCHN3V5',
        ];

        return array_get($id, $this->edition, $id['pt']);
    }

    public function topVotesLimit($phase = 'initial') {
        $topVotes = [
            'initial' => [
                'pt' => '6',
                'pt-BR' => '6',
                'es' => '6',
            ],
            'semi-final' => [
                'pt' => '1',
                'pt-BR' => '1',
                'es' => '1',
            ],
        ];

        return array_get($topVotes, "{$phase}.{$this->edition}", $topVotes[$phase]['pt']);
    }

    public function topVoted($phase = 'all') {
        $phase = $this->getDate('show-finalists')->isPast() ? 'semi-final' : 'initial';

        if (!$this->top_voted) {
            $this->top_voted = Band::orderByVotes($phase === 'all' ? 'initial' : $phase)
                    ->take($this->topVotesLimit($phase))
                    ->lists('id');
        }

        return $this->top_voted;
    }

}
