<?php

/**
 * Event internal structure representation. Plain value object.
 *
 * @author       Time.ly Network, Inc.
 * @since        2.0
 * @instantiator new
 * @package      Ai1EC
 * @subpackage   Ai1EC.Model
 */
class Ai1ec_Event_Entity extends Ai1ec_Base {

    /**
     * Get list of object properties.
     *
     * Special value `registry` ({@see Ai1ec_Registry_Object}) is excluded.
     *
     * @return array List of accessible properties.
     *
     * @staticvar array $known List of properties.
     */
    public function list_properties() {
        static $known = null;
        if ( null === $known ) {
            $known = array();
            foreach ( $this as $name => $value ) {
                $name = substr( $name, 1 );
                if ( 'registry' === $name ) {
                    continue;
                }
                $known[] = $name;
            }
        }
        return $known;
    }

    /**
     * Handle cloning properly to resist property changes.
     *
     * @return void
     */
    public function __clone() {
        $this->_start = $this->_registry->get( 'date.time', $this->_start );
        $this->_end   = $this->_registry->get( 'date.time', $this->_end );
        $this->_post  = clone $this->_post;
    }

    /**
     * Change stored property.
     *
     * @param string $name  Name of property to change.
     * @param mixed  $value Arbitrary value to use.
     *
     * @return Ai1ec_Event_Entity Instance of self for chaining.
     *
     * @staticvar array $time_fields Map of fields holding a value of
     *                               {@see Ai1ec_Date_Time}, which
     *                               require modification instead of
     *                               replacement.
     */
    public function set( $name, $value ) {
        static $time_fields = array(
            'start' => true,
            'end'   => true,
        );
        if ( 'registry' === $name ) {
            return $this; // short-circuit: protection mean.
        }
        if ( 'timezone_name' === $name && empty( $value ) ) {
            return $this; // protection against invalid TZ values.
        }
        $field = '_' . $name;
        if ( isset( $time_fields[$name] ) ) {
            // object of Ai1ec_Date_Time type is now handled in it itself
            $this->{$field}->set_date_time(
                $value,
                ( null === $this->_timezone_name )
                    ? 'UTC'
                    : $this->_timezone_name
            );
            $this->adjust_preferred_timezone();
        } else {
            $this->{$field} = $value;
        }
        if ( 'timezone_name' === $name ) {
            $this->_start->set_timezone( $value );
            $this->_end  ->set_timezone( $value );
            $this->adjust_preferred_timezone();
        }
        return $this;
    }

    /**
     * Optionally adjust preferred (display) timezone.
     *
     * @return bool|DateTimeZone False or new timezone.
     *
     * @staticvar bool $do_adjust True when adjustment should be performed.
     */
    public function adjust_preferred_timezone() {
        static $do_adjust = null;
        if ( null === $do_adjust ) {
            $do_adjust = !$this->_registry
                ->get( 'model.settings' )
                ->get( 'always_use_calendar_timezone', false );
        }
        if ( ! $do_adjust ) {
            return false;
        }
        $timezone = $this->_registry->get( 'date.timezone' )->get(
            $this->_timezone_name
        );
        $this->set_preferred_timezone( $timezone );
        return $timezone;
    }

    /**
     * Set preferred timezone to datetime fields.
     *
     * @param DateTimeZone $timezone Preferred timezone instance.
     *
     * @return void
     */
    public function set_preferred_timezone( DateTimeZone $timezone ) {
        $this->_start->set_preferred_timezone( $timezone );
        $this->_end  ->set_preferred_timezone( $timezone );
    }

    /**
     * Get a value of some property.
     *
     * @param string $name    Name of property to get.
     * @param mixed  $default Value to return if property is not defined.
     *
     * @return mixed Found value or $default.
     */
    public function get( $name, $default = null ) {
        if ( ! isset( $this->{ '_' . $name } ) ) {
            return $default;
        }
        return $this->{ '_' . $name };
    }

    /**
     * Initialize values to some sane defaults.
     *
     * @param Ai1ec_Registry_Object $registry Injected registry.
     *
     * @return void
     */
    public function __construct( Ai1ec_Registry_Object $registry ) {
        parent::__construct( $registry );
        $this->_start = $this->_registry->get( 'date.time' );
        $this->_end   = $this->_registry->get( 'date.time', '+1 hour' );
    }

    /**
     * @var object Instance of WP_Post object.
     */
    private $_post;

    /**
     * @var int Post ID.
     */
    private $_post_id;

    /**
     * @var int|null Uniquely identifies the recurrence instance of this event
     *               object. Value may be null.
     */
    private $_instance_id;

    /**
     * @var string Name of timezone to use for event times.
     */
    private $_timezone_name;

    /**
     * @var Ai1ec_Date_Time Start date-time specifier
     */
    private $_start;

    /**
     * @var Ai1ec_Date_Time End date-time specifier
     */
    private $_end;

    /**
     * @var bool Whether this copy of the event was broken up for rendering and
     *           the start time is not its "real" start time.
     */
    private $_start_truncated;

    /**
     * @var bool Whether this copy of the event was broken up for rendering and
     *           the end time is not its "real" end time.
     */
    private $_end_truncated;

    /**
     * @var int If event is all-day long
     */
    private $_allday;

    /**
     * @var int If event has no duration
     */
    private $_instant_event;

    /**
     * ==========================
     * = Recurrence information =
     * ==========================
     */

    /**
     * @var string Recurrence rules
     */
    private $_recurrence_rules;

    /**
     * @var string Exception rules
     */
    private $_exception_rules;

    /**
     * @var string Recurrence dates
     */
    private $_recurrence_dates;

    /**
     * @var string Exception dates
     */
    private $_exception_dates;

    /**
     * @var string Venue name - free text
     */
    private $_venue;

    /**
     * @var string Country name - free text
     */
    private $_country;

    /**
     * @var string Address information - free text
     */
    private $_address;

    /**
     * @var string City name - free text
     */
    private $_city;

    /**
     * @var string Province free text definition
     */
    private $_province;

    /**
     * @var int Postal code
     */
    private $_postal_code;

    /**
     * @var int Set to true to display map
     */
    private $_show_map;

    /**
     * @var int Set to true to show coordinates in description
     */
    private $_show_coordinates;

    /**
     * @var float GEO information - longitude
     */
    private $_longitude;

    /**
     * @var float GEO information - latitude
     */
    private $_latitude;

    /**
     * @var string Event contact information - contact person
     */
    private $_contact_name;

    /**
     * @var string Event contact information - phone number
     */
    private $_contact_phone;

    /**
     * @var string Event contact information - email address
     */
    private $_contact_email;

    /**
     * @var string Event contact information - external URL.
     */
    private $_contact_url;

    /**
     * @var string Defines event cost.
     */
    private $_cost;

    /**
     * @var bool Indicates, whereas event is free.
     */
    private $_is_free;

    /**
     * @var string Link to buy tickets
     */
    private $_ticket_url;

    // ====================================
    // = iCalendar feed (.ics) properties =
    // ====================================

    /**
     * @var string URI of source ICAL feed.
     */
    private $_ical_feed_url;

    /**
     * @var string|null URI of source ICAL entity.
     */
    private $_ical_source_url;

    /**
     * @var string Organiser details
     */
    private $_ical_organizer;

    /**
     * @var string Contact details
     */
    private $_ical_contact;

    /**
     * @var string|int UID of ICAL feed
     */
    private $_ical_uid;

    // ===============================
    // = taxonomy-related properties =
    // ===============================

    /**
     * @var string Associated event tag names (*not* IDs), joined by commas.
     */
    private $_tags;

    /**
     * @var string Associated event category IDs, joined by commas.
     */
    private $_categories;

    /**
     * @var string Associated event feed object
     */
    private $_feed;


}
