<?php
/**
 * CodeIgniter library
 *
 * @category CodeIgniter
 * @license /_licenses/untermStrich/agb_normal.pdf
 * @author Christian Koller
 * @copyright 2009 untermStrich
 * @package us_libraries
 * @version $Id: personalapp_values.php 26862 2024-02-01 17:03:14Z christian $
*/

if (!defined('BASEPATH')) exit('No direct script access allowed');

require_once APPPATH.'us_libraries/vendor/autoload.php';
require_once APPPATH.'us_libraries/value_objects/personalapp_values.php';

/**
 * Used to save a personal appointment
 *
 * @property    My_Controller           $CI                     The main CI object
 */
class Personalapp_values_local extends Personalapp_values
{
    /**
     * @var Sabre\VObject\Document $sabre_calendar_data_obj
     */
    protected $sabre_calendar_data_obj;
    protected $sabre_uri;
    protected $sabre_uid;

    /**
     * Extend values which were initialized from POST values
     * 
     * @param   Personalapp_values    $obj    The Personalapp_values object to extend
     * @return  void
     */    
    public function init_from_post_extend(Personalapp_values $obj): void
    {    
    }  
    
    /**
     * Retrieves the number of multi-days for the personal appointment.
     * 
     * @return integer The number of multi-days for the personal appointment.
     */    
    public function get_multidays(): int 
    {
        die(__CLASS__.'::'.__FUNCTION__." NOT IMPLEMENTED FOR LOCAL MODE - SHOULD NOT BE CALLED");
    }

    /**
     * Retrieves the attendees for the Office365 event.
     *
     * @return array The attendees for the Office365 event.
     */
    public function get_o365_attendees(): array
    {
        die(__CLASS__.'::'.__FUNCTION__." NOT IMPLEMENTED FOR LOCAL MODE - SHOULD NOT BE CALLED");
    }

    /**
     * Get the begin date for each period of a new periodical appointment
     *
     * @return  array   Array of periodical dates for a new appointment
     */
    public function get_periodical_dates(): array
    {
        die(__CLASS__.'::'.__FUNCTION__." NOT IMPLEMENTED FOR LOCAL MODE - SHOULD NOT BE CALLED");
    }

    /**
     * Increments the date and date_to, notify_date, and periodical_last_date by one day.
     *
     * @return void
     */
    public function next_day(): void
    {
        die(__CLASS__.'::'.__FUNCTION__." NOT IMPLEMENTED FOR LOCAL MODE - SHOULD NOT BE CALLED");
    }    

    /**
     * Extend values which were initialized from values
     * 
     * @param   Personalapp_values      $obj        The Personalapp_values object to extend
     * @param   stdClass                $values     The values to get extendet information
     * @return  void
     */        
    public function init_from_values_extend(Personalapp_values $obj, stdClass $values): void
    {
        if (isset($values->sabre_calendar_data_obj)) {
            $obj->sabre_calendar_data_obj = $values->sabre_calendar_data_obj;
        }     
        
        if (isset($values->sabre_uri)) {
            $obj->sabre_uri = $values->sabre_uri;
        }
        if (isset($values->sabre_uid)) {
            $obj->sabre_uid = $values->sabre_uid;
            if (!isset($values->sabre_uri)) {
                $obj->sabre_uri = $values->sabre_uid.'.ics';
            }
        }        
    }    

    /**
     * Get personal appointments to save, (handling multiuser, multiday and periodical appointments
     *
     * @return  array
     */
    public function get_appointments_to_save()
    {
        if($this->cache_appointments_to_save === null)
        {
            $this->app_type = $this->get_app_type();

            $appointments = array();
            $appointments_counter = 0;

            if ($this->add_or_id!=='add' && is_numeric($this->add_or_id)) { //EDIT
                $appointments = $this->get_appointment_to_save();
            } elseif ($this->add_or_id === 'add') { // NEW
                $arr_tmp = array();

                if ($this->notify_yn) {
                    $date = $this->date;
                    $notify_date = $this->notify_date;
                    $diff_days = datetime_diff_days($date, $notify_date);
                }

                $periodical_dates = $this->_get_periodical_dates();
                foreach ($periodical_dates as $periodical_date) {
                    $multiday_dates = $this->_get_multiday_dates(clone $periodical_date);
                    $several_days_counter = 0; // counter for several_days_day
                    foreach ($multiday_dates as $multiday_date) {
                        if(count($multiday_dates) > 1){
                            $arr_tmp['several_days'] = true;
                            $arr_tmp['several_days_day'] = $several_days_counter;
                        } else {
                            $arr_tmp['several_days'] = false;
                            $arr_tmp['several_days_day'] = 0;
                        }
                        $this->date = $multiday_date;
                        $period_plus_multiday_days = clone $periodical_date;
                        $period_plus_multiday_days->modify('+'.$this->several_days_day.' day');
                        $period_plus_multiday_days->modify('-1 day');
                        $this->several_days_last_date = clone $period_plus_multiday_days;

                        foreach ($this->multistaff as $staff_id) {
                            $this->staff = $staff_id;
                            $appointment = $this->get_appointment_to_save(); // GET EACH APPOINTMENT
                            $appointment = array_merge($appointment, $arr_tmp);

                            if ($this->notify_yn) {
                                $act_notify_date = new UsDateTime($appointment['date'], null, false);
                                $act_notify_date->modify('+'.$diff_days.' day');
                                $act_notify_date = $act_notify_date->mysqlday().' '.$this->notify_time->us_ltime();
                                $appointment['notify_date'] = $act_notify_date;
                            }
                            
                            if ($appointments_counter>0) {
                                unset($appointment['sabre_uid']);
                                unset($appointment['sabre_uri']);
                                $appointment['sabre_uid'] = \Sabre\DAV\UUIDUtil::getUUID();
                                $appointment['sabre_uri'] = $appointment['sabre_uid'].'.ics';
                            }

                            $appointments[$periodical_date->mysql()][$this->date->mysql()][$staff_id] = $appointment;
                            $appointments_counter++;
                        }
                        $several_days_counter++;
                    }
                }
            }
            $this->cache_appointments_to_save = $appointments;
        }
        
        return $this->cache_appointments_to_save;
    }

    /**
     * Get personal appointment values to save
     *
     * @return  array
     */
    public function get_appointment_to_save()
    {
        $data = parent::get_appointment_to_save();

        if (isset($this->sabre_calendar_data_obj)) {
            $data['sabre_calendar_data'] = $this->sabre_calendar_data_obj->serialize();
        }

        if (!empty((string)$this->sabre_uid)) {
            $data['sabre_uid'] = (string)$this->sabre_uid;
        } else {
            $data['sabre_uid'] = \Sabre\DAV\UUIDUtil::getUUID();
        }
        if ($this->add_or_id === 'add') {
            if (!empty((string)$this->sabre_uri)) {
                $data['sabre_uri'] = (string)$this->sabre_uri;
            } else {
                $data['sabre_uri'] = $data['sabre_uid'].'.ics';
            }
        }        
                
        return $data;
    }
    
    /**
     * Get the begin date for each period of a new periodical appointment
     *
     * @return  array   Array of periodical dates for a new appointment
     */
    private function _get_periodical_dates()
    {
        $data = array();
        $date = $this->date;
        if($this->periodical_yn === true){
            $number = $this->periodical__number;
            $unit = $this->periodical__unit;
            $unit_str = '';
            $last_date = $this->periodical_last_date;
            switch($unit)
            {
                case '1':
                    $unit_str = 'day';
                    break;
                case '2':
                    $unit_str = 'weeks';
                    break;
                case '3':
                    $unit_str = 'month';
                    break;
                case '4':
                    $unit_str = 'year';
                    break;
                default:
                    break;
            }

            while (datetime_diff($date, $last_date) >= 0) {
                $data[] = clone $date;
                $date->modify('+'.$number.' '.$unit_str);
            }
        } else { // If no periodical - return date as default periodical_last_date
            $data[] = $date;
        }
        return $data;
    }

    /**
     * Get all multiday-day dates from a given startdate
     *
     * @param   object  $date   Begindate for multidays (e.g. first day of a period [periodical appointment])
     *
     * @return  array   Array of multiday dates for a new appointment
     */
    private function _get_multiday_dates(UsDate $date)
    {
        $data = array();
        if($this->several_days_day_yn === true){
            $multiday = $this->several_days_day;
            for ($i = 0; $i < $multiday; $i++) {
                $data[] = clone $date;
                $date->modify('+1 day');
            }
        } else { // If no multiday - return date as default several_days_last_date
            $data[] = $date;
        }
        return $data;
    }

    /**
     * Get the sabre_calendar_data object
     * 
     * @return Sabre\VObject\Document
     */
    public function getSabre_calendar_data_obj(): Sabre\VObject\Document
    {
        return $this->sabre_calendar_data_obj;
    }
    
    /**
     * Returns the names of all variables of this object that should be serialized
     *
     * @return  array
     */
    public function __sleep()
    {
        return array_merge(parent::__sleep(), array(
            "sabre_uri",
            "sabre_uid"
        ));
    }    
    
}
