<?php namespace NicoSt\GCalendar\Components;

use Cms\Classes\ComponentBase;
use NicoSt\GCalendar\Classes\GoogleCalendarService;
use Mobile_Detect;

use Log;

class EmbeddedCalendar extends ComponentBase {
    private $calPropSeparator = '§§';
    private $googleEmbedUrl = 'https://calendar.google.com/calendar/embed';

    /**
     * Returns information about this component, including name and description.
     */
    public function componentDetails() {
        return [
            'name'        => 'nicost.gcalendar::lang.component.embeddedCalendar.name',
            'description' => 'nicost.gcalendar::lang.component.embeddedCalendar.description'
        ];
    }

    public function defineProperties() {

        $calendars = $this->calendarProperties();
        $customProperties = [ 
            'calendarTitle'     => [
                'title'         => 'nicost.gcalendar::lang.component.embeddedCalendar.properties.calendarTitle.title',
                'type'          => 'string'
            ],
            'width'          => [
                'title'         => 'nicost.gcalendar::lang.component.embeddedCalendar.properties.width.title',
                'type'          => 'string',
                'default'       => 1200,
                'validationPattern' => '^[0-9]{1,4}$',
                'validationMessage' => 'nicost.gcalendar::lang.component.embeddedCalendar.properties.width.validationMessage'
            ],
            'height'          => [
                'title'         => 'nicost.gcalendar::lang.component.embeddedCalendar.properties.height.title',
                'type'          => 'string',
                'default'       => 1000,
                'validationPattern' => '^[0-9]{1,4}$',
                'validationMessage' => 'nicost.gcalendar::lang.component.embeddedCalendar.properties.height.validationMessage'
            ],
            'timezone'        => [
                'title'         => 'nicost.gcalendar::lang.component.embeddedCalendar.properties.timezone.title',
                'type'          => 'dropdown',
                'default'       => 'Europe/Berlin'
            ],
            'language'        => [
                'title'         => 'nicost.gcalendar::lang.component.embeddedCalendar.properties.language.title',
                'type'          => 'dropdown',
                'default'       => 'en'
            ],
            'viewMode'        => [
                'title'         => 'nicost.gcalendar::lang.component.embeddedCalendar.properties.viewMode.title',
                'type'          => 'dropdown',
                'default'       => 'month',
                'placeholder'   => 'nicost.gcalendar::lang.component.embeddedCalendar.properties.viewMode.placeholder',
                'description'   => 'nicost.gcalendar::lang.component.embeddedCalendar.properties.viewMode.description',
                'options'       => ['month'=>'nicost.gcalendar::lang.component.embeddedCalendar.properties.viewMode.month',
                                    'week'=>'nicost.gcalendar::lang.component.embeddedCalendar.properties.viewMode.week',
                                    'agenda'=>'nicost.gcalendar::lang.component.embeddedCalendar.properties.viewMode.agenda',
                                    'dynamic'=>'nicost.gcalendar::lang.component.embeddedCalendar.properties.viewMode.dynamic']
            ],
            'weekStart'       => [
                'title'         => 'nicost.gcalendar::lang.component.embeddedCalendar.properties.weekStart.title',
                'type'          => 'dropdown',
                'default'       => 'mon',
                'options'       => ['sat'=>'nicost.gcalendar::lang.component.embeddedCalendar.properties.weekStart.sat',
                                    'sun'=>'nicost.gcalendar::lang.component.embeddedCalendar.properties.weekStart.sun',
                                    'mon'=>'nicost.gcalendar::lang.component.embeddedCalendar.properties.weekStart.mon']
            ],
            'bgcolor'         => [
                'title'         => 'nicost.gcalendar::lang.component.embeddedCalendar.properties.bgcolor.title',
                'type'          => 'string',
                'default'       => '#FFFFFF',
                'description'   => 'nicost.gcalendar::lang.component.embeddedCalendar.properties.bgcolor.description',
                'validationPattern' => '^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$',
                'validationMessage' => 'nicost.gcalendar::lang.component.embeddedCalendar.properties.bgcolor.validationMessage'
            ],
            'showTitle'       => [
                'title'         => 'nicost.gcalendar::lang.component.embeddedCalendar.properties.showTitle.title',
                'type'          => 'checkbox',
                'default'       => 1,
                'group'         => 'nicost.gcalendar::lang.component.embeddedCalendar.groups.toggleElements'
            ],
            'showPrint'       => [
                'title'         => 'nicost.gcalendar::lang.component.embeddedCalendar.properties.showPrint.title',
                'type'          => 'checkbox',
                'default'       => 1,
                'group'         => 'nicost.gcalendar::lang.component.embeddedCalendar.groups.toggleElements'
            ],
            'showTimezone'    => [
                'title'         => 'nicost.gcalendar::lang.component.embeddedCalendar.properties.showTimezone.title',
                'type'          => 'checkbox',
                'default'       => 1,
                'group'         => 'nicost.gcalendar::lang.component.embeddedCalendar.groups.toggleElements'
            ],
            'showNav'         => [
                'title'         => 'nicost.gcalendar::lang.component.embeddedCalendar.properties.showNav.title',
                'type'          => 'checkbox',
                'default'       => 1,
                'group'         => 'nicost.gcalendar::lang.component.embeddedCalendar.groups.toggleElements'
            ],
            'showDate'        => [
                'title'         => 'nicost.gcalendar::lang.component.embeddedCalendar.properties.showDate.title',
                'type'          => 'checkbox',
                'default'       => 1,
                'group'         => 'nicost.gcalendar::lang.component.embeddedCalendar.groups.toggleElements'
            ],
            'showTabs'        => [
                'title'         => 'nicost.gcalendar::lang.component.embeddedCalendar.properties.showTabs.title',
                'type'          => 'checkbox',
                'default'       => 1,
                'group'         => 'nicost.gcalendar::lang.component.embeddedCalendar.groups.toggleElements'
            ],
            'showCalendarList'=> [
                'title'         => 'nicost.gcalendar::lang.component.embeddedCalendar.properties.showCalendarList.title',
                'type'          => 'checkbox',
                'default'       => 1,
                'group'         => 'nicost.gcalendar::lang.component.embeddedCalendar.groups.toggleElements'
            ]
        ];
        $result = array_merge($customProperties, $calendars);
        
        return $result;
    }

    public function getUrl() {

        $data = [
            'showPrint'     => $this->property('showPrint', 1),
            'showTz'        => $this->property('showTimezone', 1),
            'showCalendars' => $this->property('showCalendars', 1),
            'showTabs'      => $this->property('showTabs', 1),
            'showDate'      => $this->property('showDate', 1),
            'showNav'       => $this->property('showNav', 1),
            'showTitle'     => $this->property('showTitle', 1),
            'hl'            => $this->property('language', 'en'),
            'bgcolor'       => $this->property('bgcolor', '#FFFFFF'),
            'ctz'           => $this->property('timezone'. 'Europe/Berlin')
        ];

        // Set title
        if(empty($this->property('calendarTitle')) ) {
            $data['showTitle'] = 0;
        } else {
            $data += ['title'=>$this->property('calendarTitle')];
        }

        // Set view mode
        $viewMode = $this->property('viewMode', 'month');
        if($viewMode == 'month') {
            $data += ['mode' => 'MONTH'];
        } else if($viewMode == 'agenda') {
            $data += ['mode' => 'AGENDA'];
        } else if($viewMode == 'week') {
            $data += ['mode' => 'WEEK'];
        } else if($viewMode == 'dynamic') {
            $detect = new Mobile_Detect;
            if($detect->isMobile()) {
                $data += ['mode' => 'AGENDA'];
            } else {
                $data += ['mode' => 'MONTH'];
            }
        }

        // Set week start
        $weekStart = $this->property('weekStart','mon');
        if($weekStart == 'sat') {
            $data += ['wkst' => 7];
        } else if($weekStart == 'sun') {
            $data += ['wkst' => 1];
        } else if($weekStart == 'mon') {
            $data += ['wkst' => 2];
        }

        $calendarList = $this->getCalendarsFromProperties();
        $dataParams = http_build_query($data);
        
        $calendarParams = "";
        $i = 0;
        $calCount = count($calendarList);
        foreach($calendarList as $calendarData) {
            $calQuery = http_build_query($calendarData);
            
            $calendarParams = $calendarParams.$calQuery;
            if($i != $calCount - 1){
                $calendarParams = $calendarParams.'&';
            }
            $i++;
        }
        $url = $this->googleEmbedUrl.'?'.$dataParams.'&'.$calendarParams;
        
        return $url;
    }

    public function getWidth() {
        return $this->property('width', 1200);
    }

    public function getHeight() {
        return $this->property('height', 1000);
    }

    public function getLanguageOptions() { 
        $strJsonFileContents = file_get_contents(dirname(__FILE__)."/../resources/calendar_language.json");
        return json_decode($strJsonFileContents, true);
    }

    public function getTimezoneOptions() { 
        $strJsonFileContents = file_get_contents(dirname(__FILE__)."/../resources/calendar_timezone.json");
        return json_decode($strJsonFileContents, true);
    }

    private function getCalendarsFromProperties() {
        $calendars = [];
        foreach($this->properties as $key => $value){
            $exp_key = explode($this->calPropSeparator, $key);
            if($exp_key[0] == 'cal' && $this->property($key) == true){
                $calendar = [];
                $calendar['src'] = $exp_key[2];
                $calendar['color'] = $exp_key[1];
                $calendars[] = $calendar;
            }
        }

        return $calendars;
    }

    private function calendarProperties() {
        // ToDo: Add cache => https://octobercms.com/docs/services/cache
        $service = new GoogleCalendarService();
        $calendars = $service->calendarList();

        if (isset($calendars['error'])) {
            $calendars = '';
        }

        $calendarProperties = [];
        if (!empty($calendars)) {
            foreach ($calendars as &$calendar) {
                $calendarData = [];
                $calendarData['id'] = $calendar->id;
                $calendarData['title'] = $calendar->summary;
                $calendarData['color'] = $calendar->backgroundColor;

                $property = $this->createProperty($calendarData);
                $calendarProperties = array_merge($calendarProperties, $property);
            }
        }
        return $calendarProperties;
    }

    private function createProperty(array $calendarData) {
        return [
            'cal'.$this->calPropSeparator.$calendarData['color'].$this->calPropSeparator.$calendarData['id'] => [
                'title'     => $calendarData['title'],
                'type'      => 'checkbox',
                'group'     => 'nicost.gcalendar::lang.component.embeddedCalendar.groups.calendars',
                'default'   => 0,
            ]
        ];
    }
}