<?php
	/* ****************************************************
	   Class Eventlist
	   **************************************************** */
	   
	class Eventlist {
		private $m_eventList;
		private $m_eventListPtr;
		private $m_eventCategoryPtr;
		
		// Eventlist filtering and render mode
		private $m_showCategoryFilter;
		private $m_showFilterLocation;
		private $m_showFilterCalendar;
		private $m_showFilterAvailable;
		private $m_showFilterTextSearch;
		private $m_eventListLayout;
		
        public function __construct() {
			 // Instantiate + Clear Array and Reset Pointer
			 $this->m_eventList = array();

			 
			 $this->m_eventListPtr = 0;
			 $this->m_eventCategoryPtr = 0;
			 
			 // Set defaults for eventlist filtering and render mode
			$this->m_showCategoryFilter = false;
			$this->m_showFilterLocation = false;
			$this->m_showFilterCalendar = false;
			$this->m_showFilterAvailable = false;
			$this->m_showFilterTextSearch = false;
			$this->m_eventListLayout = "Full";
        }
		
		/***********************************
		Accessor Methods
		***********************************/
		
		
		public function getNumberOfEvents() {
			return $this->m_eventListPtr;
		}
		
		public function getEvent( $a_eventIndex ) {
			return $this->m_eventList[ $a_eventIndex ];
		}
		
		public function isFilteringEnabled() {
			// Return true if either filter has been enabled
			return ( $this->m_showCategoryFilter || $this->m_showFilterLocation || $this->m_showFilterCalendar || $this->m_showFilterAvailable || $this->m_showFilterTextSearch );
		}

		public function isCategoryFilteringEnabled() {
			return ( $this->m_showCategoryFilter == "true" );
		}

		public function isLocationFilteringEnabled() {
			return ( $this->m_showFilterLocation == "true" );
		}

		public function isCalendarFilteringEnabled() {
			return ( $this->m_showFilterCalendar == "true" );
		}

		public function isAvailabilityFilteringEnabled() {
			return ( $this->m_showFilterAvailable == "true" );
		}

		public function isTextFilteringEnabled() {
			return ( $this->m_showFilterTextSearch == "true" );
		}

		public function useCompactListRendering() {
			return ( $this->m_eventListLayout != "Full" );
		}

        // --- helpers ---
        private static function str_bool($v) {
            // Convert mixed -> "true"/"false" strings to match original getters
            if (is_bool($v)) return $v ? "true" : "false";
            if (is_int($v))  return ($v === 1) ? "true" : "false";
            if (is_string($v)) {
                $lv = strtolower(trim($v));
                if ($lv === "true" || $lv === "1" || $lv === "yes" || $lv === "on")  return "true";
                if ($lv === "false"|| $lv === "0" || $lv === "no"  || $lv === "off") return "false";
            }
            return "false";
        }
        private static function arr_get($arr, $key, $default) {
            return (is_array($arr) && array_key_exists($key, $arr) && $arr[$key] !== null) ? $arr[$key] : $default;
        }

// Try to find events array regardless of nesting/keys
    private static function &findEventsArrayRef(&$root) {
        // 1) Top-level "events": [...]
        if (is_array($root) && array_key_exists('events', $root) && is_array($root['events'])) return $root['events'];
        // 2) Top-level "event-list-details": [...]
        if (is_array($root) && array_key_exists('event-list-details', $root) && is_array($root['event-list-details'])) return $root['event-list-details'];
        // 3) Nested under "event-list" (XML-ish JSON)
        if (is_array($root) && array_key_exists('event-list', $root) && is_array($root['event-list'])) {
            $el = &$root['event-list'];
            if (array_key_exists('event-list-details', $el) && is_array($el['event-list-details'])) return $el['event-list-details'];
        }
        // 4) CamelCase variants (just in case)
        if (is_array($root) && array_key_exists('eventList', $root) && is_array($root['eventList'])) {
            $el = &$root['eventList'];
            if (array_key_exists('eventListDetails', $el) && is_array($el['eventListDetails'])) return $el['eventListDetails'];
        }
        // 5) If the whole payload itself looks like an array of events
        if (is_array($root) && self::looksLikeEventItem(self::arr_get($root, 0, array()))) return $root;

        // Fallback: empty reference
        static $empty = array();
        return $empty;
    }

// Heuristic: does this array look like a single event item?
    private static function looksLikeEventItem($item) {
        if (!is_array($item)) return false;
        // Common keys we saw in your XML mapping
        return array_key_exists('event-key', $item) || array_key_exists('eventListDetails', $item) || array_key_exists('event-list-details', $item);
    }

// Map event-list-config whether it’s at top level or inside event-list
    private function loadConfigFromArray($data) {
        $cfg = null;
        if (isset($data['event-list-config']) && is_array($data['event-list-config'])) {
            $cfg = $data['event-list-config'];
        } elseif (isset($data['eventListConfig']) && is_array($data['eventListConfig'])) {
            $cfg = $data['eventListConfig'];
        } elseif (isset($data['event-list']) && is_array($data['event-list']) && isset($data['event-list']['event-list-config']) && is_array($data['event-list']['event-list-config'])) {
            $cfg = $data['event-list']['event-list-config'];
        } elseif (isset($data['eventList']) && is_array($data['eventList']) && isset($data['eventList']['eventListConfig']) && is_array($data['eventList']['eventListConfig'])) {
            $cfg = $data['eventList']['eventListConfig'];
        }
        if (!is_array($cfg)) return;

        // Write as strings "true"/"false" to match original getters
        $this->m_showCategoryFilter   = self::str_bool(self::arr_get($cfg, 'showFilterCategory',   false));
        $this->m_showFilterLocation   = self::str_bool(self::arr_get($cfg, 'showFilterLocation',   false));
        $this->m_showFilterCalendar   = self::str_bool(self::arr_get($cfg, 'showFilterCalendar',   false));
        $this->m_showFilterAvailable  = self::str_bool(self::arr_get($cfg, 'showFilterAvailable',  false));
        $this->m_showFilterTextSearch = self::str_bool(self::arr_get($cfg, 'showFilterTextSearch', false));
        $this->m_eventListLayout      = self::arr_get($cfg, 'eventListLayout', self::arr_get($cfg, 'event-list-layout', 'Full'));
    }

// ---- PUBLIC: legacy-safe JSON loader ----
    public function loadFromJson($json) {
        $data = json_decode($json, true);
        if ($data === null && function_exists('json_last_error') && json_last_error() !== JSON_ERROR_NONE) {
            return;
        }

        // Load config if present
        $this->loadConfigFromArray($data);

        // Find events array regardless of where it lives
        $events = &self::findEventsArrayRef($data);

        if (!is_array($events)) return;

        // Ensure list exists
        if (!is_array($this->m_eventList)) $this->m_eventList = array();

        foreach ($events as $ev) {
            // Some APIs nest details under 'eventListDetails' or 'event-list-details'
            if (isset($ev['eventListDetails']) && is_array($ev['eventListDetails'])) {
                $a = $ev['eventListDetails'];
            } elseif (isset($ev['event-list-details']) && is_array($ev['event-list-details'])) {
                $a = $ev['event-list-details'];
            } else {
                $a = is_array($ev) ? $ev : array();
            }

            $this->m_eventList[$this->m_eventListPtr] = new Eventlistdetails();

            // "max-available-tickets" is informational only. Whether an event is sold
            // out - and whether a waiting list is open - is told by the API through
            // "ticket-availability-status", so nothing is derived from the counts here.
            $a['open-for-registration'] = self::str_bool(self::arr_get($a, 'open-for-registration', false));


            // --- Basic details (all keys optional) ---
            $this->m_eventList[$this->m_eventListPtr]->setBasicEventDetails(
                self::arr_get($a, 'event-key', ''),                 self::arr_get($a, 'event-name', ''),
                self::arr_get($a, 'event-short-description', ''),   self::arr_get($a, 'event-description', ''),
                self::arr_get($a, 'event-start', ''),               self::str_bool(self::arr_get($a, 'event-start-visible', false)),
                self::arr_get($a, 'logo-url', ''),                  self::arr_get($a, 'flyer-url', ''),
                self::arr_get($a, 'state-key', ''),                 self::str_bool(self::arr_get($a, 'public', false)),
                self::str_bool(self::arr_get($a, 'paid-event', false)),                self::str_bool(self::arr_get($a, 'free-event', false)),
                self::str_bool(self::arr_get($a, 'open-for-registration', false)),     self::arr_get($a, 'registration-start', ''),
                self::str_bool(self::arr_get($a, 'registration-start-visible', false)),self::arr_get($a, 'registration-end', ''),
                self::str_bool(self::arr_get($a, 'registration-end-visible', false)),  self::arr_get($a, 'button-more-label', ''),
                self::arr_get($a, 'button-register-label', ''),     self::arr_get($a, 'short-title', ''),
                self::arr_get($a, 'organizer-key', ''),             self::arr_get($a, 'visible-from', ''),
                self::arr_get($a, 'visible-to', ''),                self::arr_get($a, 'event-end', ''),
                self::str_bool(self::arr_get($a, 'event-end-visible', false)),         self::arr_get($a, 'event-tags', ''),
                self::str_bool(self::arr_get($a, 'display-registered-participants', false)),
                self::str_bool(self::arr_get($a, 'show-social-widgets', false)),       self::arr_get($a, 'booking-return-target', ''),
                self::arr_get($a, 'event-type', ''),                self::arr_get($a, 'last-unregister-allowed-date', ''),
                self::arr_get($a, 'max-available-tickets', ''),     self::arr_get($a, 'sold-out-label', ''),
                self::arr_get($a, 'social-image-url', ''),          self::arr_get($a, 'facebook-pixel-id', ''),
                self::arr_get($a, 'google-analytics-id', ''),       self::arr_get($a, 'edit-event-url', ''),
                self::arr_get($a, 'not-yet-open-button-label', ''),     self::arr_get($a, 'not-open-anylonger-open-button-label', '')
            );

            // --- Ticket availability (authoritative, straight from the API) ---
            $this->m_eventList[$this->m_eventListPtr]->setAvailabilityDetails(
                /* dashed is what the API sends; the camelCase spelling is accepted as
                   well so a differently spelled key cannot silently make sold-out
                   events look available */
                self::arr_get($a, 'ticket-availability-status', self::arr_get($a, 'ticketAvailabilityStatus', '')),
                self::arr_get($a, 'sold-out-but-waitlist-open-label', self::arr_get($a, 'soldOutButWaitlistOpenLabel', ''))
            );

            // --- Location (ev may carry it or nested) ---
            $loc = null;
            if (isset($ev['location']) && is_array($ev['location'])) $loc = $ev['location'];
            if ($loc) {
                $this->m_eventList[$this->m_eventListPtr]->setLocationDetails(
                    self::arr_get($loc, 'name', ''), self::arr_get($loc, 'description', ''),
                    self::arr_get($loc, 'address', ''), self::arr_get($loc, 'geo-location', ''),
                    self::arr_get($loc, 'logo-url', '')
                );
            }

            // --- Account ---
            if (isset($ev['account']) && is_array($ev['account'])) {
                $acc = $ev['account'];
                $this->m_eventList[$this->m_eventListPtr]->setAccountDetails(
                    self::arr_get($acc, 'minimum-price-to-pay', ''), self::arr_get($acc, 'currency-code', ''),
                    self::arr_get($acc, 'fixed-price', ''),          self::arr_get($acc, 'short-price-description', ''),
                    self::arr_get($acc, 'rich-price-description', '')
                );
            }

            // Always start a clean designation list for each event
            $this->m_eventList[$this->m_eventListPtr]->createDesignationList();

// Collect designations from JSON (supports both shapes)
            $designations = array();

            if (isset($ev['participant-designations']) && is_array($ev['participant-designations'])) {
                // Flat array shape
                $designations = $ev['participant-designations'];

            } elseif (isset($ev['participant-designation-list']) && is_array($ev['participant-designation-list'])) {
                // Nested shape like in your sample
                $pdl = $ev['participant-designation-list'];
                if (isset($pdl['participant-designation'])) {
                    // It can be either a single object or an array
                    if (is_array($pdl['participant-designation']) && array_key_exists(0, $pdl['participant-designation'])) {
                        $designations = $pdl['participant-designation'];
                    } else {
                        $designations = array($pdl['participant-designation']);
                    }
                }
            }

            if (!empty($designations)) {
                foreach ($designations as $d) {
                    if (!is_array($d)) continue;

                    $this->m_eventList[$this->m_eventListPtr]->setDesignations(
                        self::arr_get($d, 'participant-designation-name', ''),
                        self::arr_get($d, 'participant-designation-description', ''),
                        (int) self::arr_get($d, 'max-participants', 0),
                        (int) self::arr_get($d, 'max-participants-per-customer', 0),
                        (int) self::arr_get($d, 'reserved-total', 0)
                    );
                }
            }


            // --- Price info ---
            if (isset($ev['event-price-info']) && is_array($ev['event-price-info'])) {
                $pi = $ev['event-price-info'];
                if (isset($pi['minimum-price-to-pay']) && $pi['minimum-price-to-pay'] !== '') {
                    $this->m_eventList[$this->m_eventListPtr]->setEventPriceInfo(
                        self::arr_get($pi, 'minimum-price-to-pay', ''),
                        self::arr_get($pi, 'maximum-price-to-pay', ''),
                        self::arr_get($pi, 'fixed-price', '')
                    );
                }
            }

            // --- Categories ---
            $this->m_eventCategoryPtr = 0;
            $this->m_eventList[$this->m_eventListPtr]->createCategoryList();

            $cats = array();

// Shape 1: flat array
            if (isset($ev['categories']) && is_array($ev['categories'])) {
                $cats = $ev['categories'];

// Shape 2: nested (like your sample)
            } elseif (isset($ev['event-category-list']) && is_array($ev['event-category-list'])) {
                $ecl = $ev['event-category-list'];
                if (isset($ecl['category'])) {
                    // may be a single object or an array
                    if (is_array($ecl['category']) && array_key_exists(0, $ecl['category'])) {
                        $cats = $ecl['category'];
                    } else {
                        $cats = array($ecl['category']);
                    }
                }

// Optional: camelCase variant
            } elseif (isset($ev['eventCategoryList']) && is_array($ev['eventCategoryList'])) {
                $ecl = $ev['eventCategoryList'];
                if (isset($ecl['category'])) {
                    if (is_array($ecl['category']) && array_key_exists(0, $ecl['category'])) {
                        $cats = $ecl['category'];
                    } else {
                        $cats = array($ecl['category']);
                    }
                }
            }

            if (!empty($cats)) {
                foreach ($cats as $cat) {
                    if (!is_array($cat)) continue;

                    // Allow both dash-case and camelCase keys from JSON
                    $ext  = self::arr_get($cat, 'external-key', self::arr_get($cat, 'externalKey', ''));
                    $name = self::arr_get($cat, 'display-name', self::arr_get($cat, 'displayName', ''));

                    // An empty "category" list parses as one empty entry - skip it
                    if ($ext === '' && $name === '') continue;

                    $this->m_eventList[$this->m_eventListPtr]->setCategory(
                        $this->m_eventCategoryPtr++,
                        $ext,
                        $name
                    );
                }
            }


            $this->m_eventListPtr++;
        }
    }

	}
?>