<?php

use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
use Clumsy\CMS\Models\BaseModel;
use Clumsy\Eminem\Traits\Mediable;

class Band extends BaseModel implements UserInterface, RemindableInterface {

    use Mediable;

    public $columns = array(
        'name' => 'Nome do fadista',
        'song' => 'Música',
        'display_created_at' => 'Inscrição',
        'initial_votes_count' => 'Votos',
        'semi_votes_count' => 'Votos Semi-final',
        'votes_count' => 'Total Votos',
        'status' => 'Estado',
        'jury_rating' => 'Avaliação do juri',
        'selected' => 'Selecionado',
        'nationality' => 'Nacionalidade',
    );
    //public $visible = array('jury_rating');
    public $booleans = array(
        'approved',
        'rejected',
        'shortlist',
        'final',
        'winner',
        'selected'
    );
    public $default_order = array(
        'created_at' => 'desc',
    );
    public $order_equivalence = array(
        'display_created_at' => 'created_at',
    );
    public $filters = array(
        'name',
        'song',
    );
    public $rules = array(
        'name' => 'required|max:255',
        'bio' => 'required|max:500',
        'song' => 'required|max:255',
        'video_url' => 'required|max:255',
        'phone' => 'required|max:255',
        'city' => 'required|max:255',
        'email' => 'required|email|max:255',
        'password' => 'min:6|max:255',
        'alternative_name' => 'required|max:255',
        'alternative_email' => 'required|email|max:255',
        'alternative_phone' => 'required|max:255',
        'image' => 'image|max:2048',
    );
    public $toggle_filters = array(
        'all' => 'Todos',
        'shortlist' => 'Shortlist',
        'pending' => 'Pendentes',
        'approved' => 'Aprovados',
        'rejected' => 'Rejeitados',
        'selected' => 'Selecção EDP',
    );
    public $suppress_when_toggled = array(
        'status',
    );
    public $appends = array(
        'jury_rating'
    );

    /**
     * The attributes excluded from the model's JSON form.
     *
     * @var array
     */
    protected $hidden = array('password');

    public static function boot() {
        parent::boot();

        if(isset($_REQUEST['media_bind'])) {

            self::saved(function($model) {
                $model->generateImageTypes();
            });

        }
//
//        self::saved(function($model) {
//            $model->generateImageTypes();
//        });

    }

    public function getJuryRatingAttribute() {
        return $this->juryVotes->sum('rating');
    }

    public function juryVotes() {
        return $this->hasMany(JuryVote::class)->orderBy('voter_id');
    }

    public function hasJurorRating($jurorId) {
        $rating = JuryVote::where('voter_id', $jurorId)
                ->where('band_id', $this->id)
                ->first();

        return is_null($rating) ? 0 : $rating->rating;
    }

    /**
     * Get the unique identifier for the user.
     *
     * @return mixed
     */
    public function getAuthIdentifier() {
        return $this->getKey();
    }

    /**
     * Get the password for the user.
     *
     * @return string
     */
    public function getAuthPassword() {
        return $this->password;
    }

    /**
     * Get the token value for the "remember me" session.
     *
     * @return string
     */
    public function getRememberToken() {
        return $this->remember_token;
    }

    /**
     * Set the token value for the "remember me" session.
     *
     * @param  string  $value
     * @return void
     */
    public function setRememberToken($value) {
        $this->remember_token = $value;
    }

    /**
     * Get the column name for the "remember me" token.
     *
     * @return string
     */
    public function getRememberTokenName() {
        return 'remember_token';
    }

    /**
     * Get the e-mail address where password reminders are sent.
     *
     * @return string
     */
    public function getReminderEmail() {
        return $this->email;
    }

    public static function rules() {
        $rules = with(new self)->rules;

        $rules['name'] .= '|unique:bands';
        $rules['password'] = 'required|' . $rules['password'];
        $rules['image'] = 'required|' . $rules['image'];

        return $rules;
    }

    public function hasVoteFromUser($id = null) {
        $vote = Vote::where('voter_id', $id)->where('band_id', $this->id)->first();

        return is_null($vote) ? false : true;
    }

    public function elements() {
        return $this->hasMany(BandMember::class);
    }

    public function votes() {
        return $this->hasMany('Vote')->groupBy('voter_id', 'band_id', 'phase')->orderBy('created_at', 'desc');
    }

    public function initialVotes() {
        return $this->hasMany('Vote')
                        ->where('phase', 'initial')
                        ->groupBy('voter_id', 'band_id');
    }

    public function semiFinalVotes() {
        return $this->hasMany('Vote')
                        ->where('phase', 'semi-final')
                        ->groupBy('voter_id', 'band_id');
    }

    public function scopeOfType($query, $type) {
        switch ($type) {
            case 'shortlist' :
                return $query->where('shortlist', true);

            case 'approved' :
                return $query->where('approved', true)
                                ->where('rejected', false);

            case 'pending' :
                return $query->where('approved', false)
                                ->where('rejected', false);

            case 'rejected' :
                return $query->where('rejected', true);

            case 'selected' :
                return $query->where('approved', true)
                                ->where('selected', true);
        }
    }

    public function scopeOrderByVotes($query, $phase = 'all') {
        $query->select('bands.*', DB::raw('count(`votes`.`band_id`) as vote_count'))
                ->leftJoin('votes', 'votes.band_id', '=', 'bands.id')
                ->groupBy('bands.id')
                ->orderBy('vote_count', 'desc');

        if ($phase !== 'all') {
            $query->where('phase', $phase);
        }
    }

    public function extractYoutubeId($url) {
        if (preg_match('/^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#\&\?]*).*/', $url, $match)) {
            return last($match);
        }

        return false;
    }

    public function getMainYoutubeIdAttribute($url) {
        if ($this->second_youtube_id) {
            return $this->second_youtube_id;
        }

        return $this->youtube_id;
    }

    public function getYoutubeIdAttribute($url) {
        if ($id = $this->extractYoutubeId($this->video_url)) {
            return $id;
        }

        return $this->video_url;
    }

    public function getSecondYoutubeIdAttribute($url) {
        if ($id = $this->extractYoutubeId($this->second_video_url)) {
            return $id;
        }

        return $this->second_video_url;
    }

    public function getInterviewYoutubeIdAttribute($url) {
        if ($id = $this->extractYoutubeId($this->interview_url)) {
            return $id;
        }

        return $this->interview_url;
    }

    public function getDisplayCreatedAtAttribute() {
        return display_date($this->created_at, 'short with time');
    }

    public function getStatusAttribute() {
        if (!$this->approved && !$this->rejected) {
            return 'Pendente';
        }

        return ($this->approved && !$this->rejected) ? 'Aprovada' : 'Rejeitada';
    }

    public function getResultBadgeAttribute() {
        if (!$this->shortlist) {
            return null;
        }

        return in_array($this->id, Contest::topVoted()) ? trans('frontend.escolha_publico') : trans('frontend.escolha_juri');
    }

    public function getPhaseVotesCountAttribute() {
        return Contest::status() === 'semi-final' ? $this->semiFinalVotes->count() : $this->votes->count();
    }

    public function getVotesCountAttribute() {
        return $this->votes->count();
    }

    public function getInitialVotesCountAttribute() {
        return $this->initialVotes->count();
    }

    public function getSemiVotesCountAttribute() {
        return $this->semiFinalVotes->count();
    }

    public function getShortNameAttribute() {
        if (strlen($this->name) > 14) {
            return substr($this->name, 0, 14) . '...';
        }

        return $this->name;
    }

    public function getPermalinkAttribute() {
        return url(route('band', array('slug' => $this->slug)));
    }

    public function getRealImageUrlAttribute() {
        return $this->mediaPath('image');
    }

    public function getImageUrlAttribute() {
        if (!$this->hasMedia('thumbnail')) {
            return url('assets/img/placeholder.jpg');
        }

//        $imagePathInfo = pathinfo($this->mediaPath('image'));
//
//        $thumbnailFileName = "{$imagePathInfo['dirname']}/{$imagePathInfo['filename']}-thumbnail.{$imagePathInfo['extension']}";
//
//        $thumbnailFileName = str_replace(url(), public_path(), $thumbnailFileName);
//
//        if (!$this->hasMedia('thumbnail') || !file_exists($thumbnailFileName)) {
//            $imagePath = str_replace(url(), public_path(), $this->mediaPath('image'));
//
//            try {
//
//                $fileName = last(explode('/', $this->mediaPath('image')));
//
//                $extension = pathinfo($fileName)['extension'];
//                $name = pathinfo($fileName)['filename'];
//
//                $img = Image::make($imagePath)
//                        ->fit(427, 240)
//                        ->save(public_path() . "/uploads/band-images/{$name}-thumbnail.{$extension}");
//
//                $this->addToMediaSlot('thumbnail', "{$img->dirname}/{$img->filename}.{$extension}");
//            } catch (\Exception $e) {
//                return url('assets/img/placeholder.jpg');
//            }
//        }

        return $this->mediaPath('thumbnail');
    }

    public function generateImageTypes() {
        try {
            $this->generateImageType('tiny-thumbnail');
            $this->generateImageType('thumbnail');


            return true;
        } catch (\Exception $e) {
            return false;
        }
    }

    public function getTinyImageUrlAttribute() {
        if (!$this->hasMedia('tiny-thumbnail')) {
            return url('assets/img/placeholder.jpg');
        }

//        $imagePathInfo = pathinfo($this->mediaPath('image'));
//
//        $thumbnailFileName = "{$imagePathInfo['dirname']}/{$imagePathInfo['filename']}-tiny-thumbnail.{$imagePathInfo['extension']}";
//
//        $thumbnailFileName = str_replace(url(), public_path(), $thumbnailFileName);
//
//        if (!$this->hasMedia('tiny-thumbnail') || !file_exists($thumbnailFileName)) {
//            //exit(__FILE__ . '--' . __LINE__);
//            $imagePath = str_replace(url(), public_path(), $this->mediaPath('image'));
//
//            try {
//
//                $fileName = last(explode('/', $this->mediaPath('image')));
//
//                $extension = pathinfo($fileName)['extension'];
//                $name = pathinfo($fileName)['filename'];
//
//                $img = Image::make($imagePath)
//                        ->fit(427, 240)
//                        ->save(public_path() . "/uploads/band-images/{$name}-tiny-thumbnail.{$extension}");
//
//                $this->addToMediaSlot('tiny-thumbnail', "{$img->dirname}/{$img->filename}.{$extension}");
//            } catch (\Exception $e) {
//                return url('assets/img/placeholder.jpg');
//            }
//        }

        return $this->mediaPath('tiny-thumbnail');
    }

    public function generateImageType($type) {
        if (!$this->hasMedia('image')) {
            return false;
        }
        $imagePathInfo = pathinfo($this->mediaPath('image'));
        $thumbnailFileName = "{$imagePathInfo['dirname']}/{$imagePathInfo['filename']}-{$type}.{$imagePathInfo['extension']}";
        $thumbnailFileName = str_replace(url(), public_path(), $thumbnailFileName);

        $imagePath = str_replace(url(), public_path(), $this->mediaPath('image'));

        try {

            $fileName = last(explode('/', $this->mediaPath('image')));

            $extension = pathinfo($fileName)['extension'];
            $name = pathinfo($fileName)['filename'];

            $imagePathToSave = public_path() . "/uploads/band-images/{$name}-{$type}.{$extension}";
            $img = Image::make($imagePath)
                    ->fit(427, 240)
                    ->save($imagePathToSave);



            $this->addToMediaSlot($type, "{$img->dirname}/{$img->filename}.{$extension}");
        } catch (\Exception $e) {
            return false;
        }


        return true;
    }

    public function notify($status, $reasons = null) {
        $band = $this;
        $edition = Contest::getEdition();

        if ($status === 'shortlist' || $status === 'final') {

            if ($this->pendingNotification($status)) {

                Mail::send("emails.{$edition}.{$status}", compact('band', 'reasons', 'edition'), function($message) use($band, $status, $edition) {
                    $message
                            ->replyTo(Contest::email())
                            ->from(Contest::emailFrom(), 'EDP Tanto Fado')
                            ->to($band->email, 'EDP Tanto Fado')
                            ->cc(Contest::email())
                            ->subject($status === 'shortlist' ?
                                        trans('emails.shortlist.subject', array('title' => Contest::title()), 'messages', $edition) :
                                        trans('emails.final.subject', array('title' => Contest::title(), 'messages', $edition))
                                     );
                });

                return true;
            }

            return false;
        }

        $subject = trans(
                'emails.rejected.subject', array('title' => Contest::title()), 'messages', $edition
        );

        if ($status === 'approved') {
            $subject = trans(
                    'emails.approved.subject', array('title' => Contest::title()), 'messages', $edition
            );
        }
        try {
            Mail::send("emails.{$edition}.{$status}", compact('band', 'reasons', 'edition'), function($message) use($band, $status, $subject) {

                $message
                        ->replyTo(Contest::email())
                        ->from(Contest::email(), 'EDP Tanto Fado')
                        ->to($band->email, 'EDP Tanto Fado')
                        ->subject($subject);
            });
        } catch (Exception $ex) {
             var_dump($ex->getMessage())       ;
             exit(__FILE__ . '--' . __LINE__);

        }
    }

    /**
     *
     * Generates a random password and updates the band information returning  the password in plain text
     *
     * @return string
     *
     */
    protected function regeneratePassword() {
        $alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
        $pass = array(); //remember to declare $pass as an array
        $alphaLength = strlen($alphabet) - 1; //put the length -1 in cache
        for ($i = 0; $i < 12; $i++) {
            $n = rand(0, $alphaLength);
            $pass[] = $alphabet[$n];
        }
        $textPassword = implode($pass);

        $password = Hash::make($textPassword);
        $this->password = $password;
        $this->save();
        return $textPassword;
    }

    /**
     *
     * Regenerates the band password and sends it to the band main email
     *
     * @return boolean
     */
    public function resendAccess() {
        $band = $this;
        $edition = Contest::getEdition();
        $newPassword = $this->regeneratePassword();

        $subject = trans('emails.resend.subject',[], 'messages', $edition);

        try {
            $res = Mail::send("emails.{$edition}.resendpwd", compact('band', 'edition', 'newPassword'), function($message) use($band, $subject) {

                        $message
                                ->replyTo(Contest::email())
                                ->from(Contest::email(), 'EDP Tanto Fado')
                                ->to($band->email, 'EDP Tanto Fado')
                                ->subject($subject);
                    });
            return true;
        } catch (Exception $ex) {

        }
        return false;
    }

    public function pendingNotification($status) {
        if ($status === 'shortlist') {
            return $this->shortlist && !$this->semifinal_notification;
        }

        return $this->final && !$this->final_notification;
    }

    public function mediaSlots() {
        return array(
            array(
                'position' => 'image',
                'label' => 'Imagem'
            ),
            array(
                'position' => 'thumbnail',
                'label' => 'Miniatura'
            ),
            array(
                'position' => 'tiny-thumbnail',
                'label' => 'Mini-miniatura'
            ),
        );
    }

    public function displayName() {
        return 'Fadista';
    }

    public function displayNamePlural() {
        return 'Fadistas';
    }

    public function rowClass() {
        return Str::slug($this->status);
    }


    public function getBadgeAttribute(){
        if ($this->winner){
            return trans('api.badges.winner');
        }elseif ($this->final){
            return trans('api.badges.finalist');
        }elseif ($this->shortlist){
            return trans('api.badges.semi_finalist');
        }
        return trans('api.badges.participant');
    }

    /**
     * Gets a band record formatted for the API
     */
    public function getApiDetailFormattedRecord() {
        $ret = new stdClass();
        $ret->id = $this->id;
        $ret->name = $this->name;
        $ret->video_url = $this->video_url;
        $ret->second_video_url = $this->second_video_url;
        $ret->interview_url = $this->interview_url;
        $ret->bio = $this->bio;
        $ret->votes = $this->getPhaseVotesCountAttribute();
        $ret->image = $this->realImageUrl;
        $ret->voting_badge = $this->resultBadge;
        $ret->members = $this->getElements();

        if($this->approved == 0) {
            $ret->image = '';
        }

        return $ret;
    }


    /**
     * Gets a band record formatted for the API
     */
    public function getApiFormattedRecord(){

        $ret = new stdClass();
        $ret->id = $this->id;
        $ret->updated_at = $this->updated_at->format('Y-m-d H:i:s');
        $ret->name = $this->name;
        $ret->slug = $this->slug;
        $ret->song = $this->song;
        $ret->video_url = $this->video_url;
        $ret->interview_url = $this->interview_url;
        $ret->bio = $this->bio;
        $ret->shortlist = $this->shortlist;
        $ret->winner = $this->winner;
        $ret->final = $this->final;
        $ret->second_video_url = $this->second_video_url;
        $ret->interview_url = $this->interview_url;
        $ret->votes = $this->getPhaseVotesCountAttribute();
        $ret->image = $this->realImageUrl;
        $ret->voting_badge = $this->resultBadge;
        $ret->members = $this->getElements();

        if($this->approved == 0) {
            $ret->image = '';
        }

        return $ret;
    }

    private function getElements() {
        $result = [];

        foreach($this->elements as $element) {
            $result[] = [
                'name' => $element->name,
                'function' => $element->function,
            ];
        }

        return $result;
    }

}
