<?php
class Calendarista_UpcomingAppointmentResultList extends Calendarista_UList {
	public $perPage;
	public $orderBy;
	public $projects;
	protected $pages;
	protected $generalSetting;
	protected $availabilityRepo;
	protected $bookedAvailabilityRepo;
	protected $availability;
	protected $timezone;
	protected $clientTime;
  function __construct($projects = null){
	  $this->projects = $projects;
	  $this->pages = $this->prepareGetPageLink();
		parent::__construct( array(
            'singular'  => 'order', 
            'plural'    => 'orders', 
            'ajax'      => false    
        ) );
		$repo = new Calendarista_GeneralSettingsRepository();
		$this->generalSetting = $repo->read();
		$this->availabilityRepo = new Calendarista_AvailabilityRepository();
		$this->bookedAvailabilityRepo = new Calendarista_BookedAvailabilityRepository();
		$this->timezone = isset($_REQUEST['timezone']) ? sanitize_text_field($_REQUEST['timezone']) : null;
		$this->clientTime = isset($_REQUEST['clientTime']) ? sanitize_text_field($_REQUEST['clientTime']) : null;
    }
    
	function single_row( $item ) {
		echo $this->single_row_columns( $item );
	}
	
    function column_default($item, $column_name){
        switch($column_name){
            default:
                return print_r($item,true); 
        }
    }
    function editable($item, $editPolicy){
		if($editPolicy > 0){
			$fromDate = $item['fromDate'];
			$toDate = $item['toDate'];
			$originalTimezone = $item['serverTimezone'] ? Calendarista_TimeHelper::setTimezone($item['serverTimezone']) : null;
			$bookingDate = $fromDate;
			if($fromDate != $toDate){
				$bookingDate = $toDate;
			}
			$bookingDate = strtotime($bookingDate);
			$now = strtotime('now');
			if($bookingDate < $now){
				//booking is already expired
				if($originalTimezone){
					Calendarista_TimeHelper::setTimezone($originalTimezone);
				}
				return false;
			}
			$editPolicy = strtotime('+' . $editPolicy . ' minutes', $now);
			if($editPolicy > $bookingDate){
				//cannot cancel, violating policy
				if($originalTimezone){
					Calendarista_TimeHelper::setTimezone($originalTimezone);
				}
				return false;
			}
			if($originalTimezone){
				Calendarista_TimeHelper::setTimezone($originalTimezone);
			}
		}
		return true;
	}
	function column_item($item){
		$enableEdit = isset($_POST['enableEdit']) ? filter_var($_POST['enableEdit'], FILTER_VALIDATE_BOOLEAN) : false;
		$editPolicy = isset($_POST['editPolicy']) ? (int)$_POST['editPolicy'] : 0;
		$handlerUrl = add_query_arg(array('calendarista_handler'=>'add_to_calendar', 'orderId'=>$item['orderId']), site_url());
		$googleUrlFeed = Calendarista_AddToCalendarButtonHelper::google(array($item));
		$status = (int)$item['status'];
		$cancelButton = null;
		$editButton = null;
		if($this->allowsCancel($item)){
			$cancelButton = sprintf(
				'<button type="button" class="btn btn-light" name="bookedAvailabilityId" value="%d" title="%s" %s>%s</button>
				<input type="hidden" id="order_id_%d" value="%d">'
				, $item['id']
				, __('Cancel Appointment', 'calendarista')
				, $status === Calendarista_AvailabilityStatus::CANCELLED ? 'disabled' : ''
				, __('Cancel', 'calendarista')
				, $item['id']
				, $item['orderId']
			);
		}
		if($enableEdit && $this->editable($item, $editPolicy)){
			$editButton = sprintf(
				'<button type="button" 
					class="btn btn-light" 
					name="editAppointment"
					data-calendarista-project-id="%d"
					data-calendarista-availability-id="%d"
					data-calendarista-booked-availability-id="%d"
					value="%d" title="%s" %s>%s</button>'
				, $item['projectId']
				, $item['availabilityId']
				, $item['id']
				, $item['orderId']
				, __('Edit Appointment', 'calendarista')
				, $status === Calendarista_AvailabilityStatus::CANCELLED ? 'disabled' : ''
				, __('Edit', 'calendarista')
			);
		}
		$title = sprintf('%s - %s', $item['projectName'], $item['availabilityName']);
		$appointmentStatus = sprintf('<span class="badge text-bg-success" title="%s">&nbsp;</span>', __('CONFIRMED', 'calendarista'));
		if($status === Calendarista_AvailabilityStatus::PENDING){
			$appointmentStatus = sprintf('<span class="badge text-bg-warning" title="%s">&nbsp;</span>', __('PENDING', 'calendarista'));
		}else if($status === Calendarista_AvailabilityStatus::CANCELLED){
			$appointmentStatus = sprintf('<span class="badge text-bg-danger" title="%s">&nbsp;</span>', __('CANCELLED', 'calendarista'));
		}
		$availableDate = Calendarista_TimeHelper::formatDate($item['fromDate']);
		$endDate = null;
		if(date(CALENDARISTA_DATEFORMAT, strtotime($item['fromDate'])) !== date(CALENDARISTA_DATEFORMAT, strtotime($item['toDate']))){
			$endDate = Calendarista_TimeHelper::formatDate($item['toDate']);
		}
		$startTime = null;
		$endTime = null;
		if($item['startTimeId'] && (int)$item['startTimeId'] !== -1){
			$timeslot = date("H:i", strtotime($item['fromDate']));
			$startTime = Calendarista_TimeHelper::formatTime(array(
				'timezone'=>null
				, 'serverTimezone'=>null
				, 'time'=>$timeslot
			));
		}
		if($item['endTimeId'] && (int)$item['endTimeId'] !== -1){
			$timeslot = date("H:i", strtotime($item['toDate']));
			$endTime = Calendarista_TimeHelper::formatTime(array(
				'timezone'=>null
				, 'serverTimezone'=>null
				, 'time'=>$timeslot
			));
		}
		$appointmentStartDate = trim($availableDate . ' ' . $startTime);
		$appointmentEndDate = null;
		if($endTime && date(CALENDARISTA_DATEFORMAT, strtotime($item['fromDate'])) === date(CALENDARISTA_DATEFORMAT, strtotime($item['toDate']))){
			$appointmentStartDate .= sprintf(' - %s', $endTime);
		}else if($endDate){
			$appointmentEndDate = trim($endDate . ' ' . $endTime);
		}
		$startLabel = null;
		$endLabel = null;
		if($appointmentEndDate){
			$startLabel = __('Starts on: ', 'calendarista');
			$endLabel = __('Ends on: ', 'calendarista');
		}
		$description = '';
		$optionals = Calendarista_NotificationEmailer::getOptionals((int)$item['orderId']);
		$customFormFields = Calendarista_NotificationEmailer::getCustomFormElements((int)$item['orderId']);
		$dynamicFields = Calendarista_NotificationEmailer::getDynamicFields((int)$item['orderId']);
		$mapInfo = $this->getMapInfo((int)$item['orderId']);
		if($mapInfo){
			$description .= sprintf('<div class="calendarista_child_item%d collapse mb-1 calendarista-typography--caption1 calendarista-description-toggle">%s</div>', $item['id'], $mapInfo);
		}
		if($optionals){
			$description .= sprintf('<div class="calendarista_child_item%d collapse mb-1 calendarista-typography--caption1 calendarista-description-toggle">%s</div>', $item['id'], $optionals);
		}
		if($customFormFields){
			$description .= sprintf('<div class="calendarista_child_item%d collapse mb-1 calendarista-typography--caption1 calendarista-description-toggle">%s</div>', $item['id'], $customFormFields);
		}
		if($dynamicFields){
			$description .= sprintf('<div class="calendarista_child_item%d collapse mb-1 calendarista-typography--caption1 calendarista-description-toggle">%s</div>', $item['id'], $dynamicFields);
		}
		if($description){
			$description = sprintf('<div class="mb-1 calendarista-viewmore" data-bs-toggle="collapse" data-bs-target=".calendarista_child_item%d" data-calendarista-id="calendarista_child_item%d"><span class="badge text-bg-info"><i class="fa fa-plus"></i> %s</span></div>%s',$item['id'] ,$item['id'], __('Appointment details', 'calendarista'), $description);
		}
		$result = '<div class="container">';
		$result .= 		'<div class="row align-items-center">';
		$result .= 			'<div class="col-1">';
		$result .= 				$appointmentStatus;
		$result .=			'</div>';//col-1
		if($cancelButton || $editButton){
		$result .= 			'<div class="col-8">';
		} else{
		$result .= 			'<div class="col-11">';	
		}
		$result .= 				'<div class="container">';
		$result .= 					'<div class="row align-items-center">';
		$result .= 							'<div class="col-md-auto h-100">';
		$result .= 								'<div class="mb-1 calendarista-typography--subtitle2">' . $title . '</div>';
		$result .= 								'<div class="mb-1 calendarista-typography--subtitle2"><i class="fa fa-calendar"></i> ' . trim(sprintf('%s %s', $startLabel, $appointmentStartDate)) . '</div>';
		if($appointmentEndDate){
			$result .= 							'<div class="mb-1 calendarista-typography--subtitle2"><i class="fa fa-calendar"></i> ' . trim(sprintf('%s %s', $endLabel, $appointmentEndDate)) . '</div>';
		}
		if($description){
			$result .= $description;
		}
		$result .=									'<hr>';
		$result .=									'<p class="calendarista-typography--subtitle4 calendarista-add-to-calendar-line">';
		$result .=											__('Add to', 'calendarista');
		$result .=											':&nbsp;&nbsp;';
		$result .=										'<a href="' . $handlerUrl . '" target="_blank" class="calendarista-add-to-calendar-link">';
		$result .=											__('iCal', 'calendarista');
		$result .=										'</a>&nbsp;-&nbsp;';
		$result .=										'<a href="' . $handlerUrl . '" target="_blank" class="calendarista-add-to-calendar-link">';
		$result .=											__('OutLook', 'calendarista');
		$result .=										'</a>&nbsp;-&nbsp;';
		$result .=										'<a href="' . $googleUrlFeed . '" target="_blank" class="calendarista-add-to-calendar-link">';
		$result .=											__('Google', 'calendarista');
		$result .=										'</a>';
		$result .=									'</p>';
		$result .= 							'</div>';//col h-100
		$result .= 					'</div>';//row
		$result .= 				'</div>';//container
		$result .= 			'</div>';//col-8
		if($cancelButton || $editButton){
		$result .= 			'<div class="col-3">';
		$result .= 				'<div class="container">';
		$result .= 					'<div class="row">';
		$result .= 						'<div class="col">';
		$result .= 							'<div class="col-md-auto h-100 w-100">';
		$result .=								'<div class="text-end">';
		if($editButton){
			$result .= 									$editButton;
		}
		if($editButton && $cancelButton){
			$result .= '</div>';
			$result .= '<div class="text-end calendarista-user-profile-margin-top">';
		}
		if($cancelButton){
			$result .= 									$cancelButton;
		}
		$result .=								'</div>';//text-end
		$result .=							'</div>';//col-md-auto h-100 w-100
		$result .=						'</div>';//col
		$result .=					'</div>';//row
		$result .=				'</div>';//container
		$result .= 			'</div>';//col-3
		}
		$result .= 		'</div>';//row
		$result .= 	'</div>';//container
		return $result;
	}
	function getMapInfo($orderId){
		$map = Calendarista_NotificationEmailer::getMap($orderId);
		$waypoints = Calendarista_NotificationEmailer::getWaypoints($orderId);
		//$mapLink = Calendarista_NotificationEmailer::getMapLink($map, $waypoints);
		$result = '';
		if($map && $map->fromAddress){
			$result .= sprintf('<br>%s: %s', __('Departure from', 'calendarista'), $map->fromAddress);
		}
		if($waypoints !== null){
			$result .= sprintf('<br>%s:<br>%s', __('Stops on the way', 'calendarista'), $waypoints);
		}
		if($map && $map->toAddress){
			$result .= sprintf('<br>%s: %s', __('Destination to', 'calendarista'), $map->toAddress);
		}
		if($map && (float)$map->distance > 0){
			$unitType = (int)$map->unitType === 0 ? __('km', 'calendarista') : __('miles', 'calendarista');
			$distanceLabel = __('The total distance is for', 'calendarista');
			$result .= sprintf('<br>%s %s%s', $distanceLabel, Calendarista_MoneyHelper::toDouble((float)$map->distance), $unitType);
		}
		if($map && (float)$map->duration > 0){
			$timeUnitLabels = array(
				'day'=>__('day(s)', 'calendarista')
				, 'hour'=>__('hr', 'calendarista')
				, 'minute'=>__('min', 'calendarista')
				, 'second'=>__('sec', 'calendarista') 
			);
			$result .= sprintf('<br>%s: %s', __('The estimated duration is', 'calendarista'),  Calendarista_TimeHelper::secondsToTime((float)$map->duration, $timeUnitLabels));
		}
		return $result;
	}
	function allowsCancel($item){
		if(!$this->generalSetting->enableUserCancelBooking){
			return false;
		}
		$status = (int)$item['status'];
		if($status === Calendarista_AvailabilityStatus::CANCELLED){
			return false;
		}
		$availabilityId = (int)$item['availabilityId'];
		if(!$this->availability || $availabilityId !== $this->availability->id){
			$this->availability = $this->availabilityRepo->read($availabilityId);
		}
		$originalTimezone = Calendarista_TimeHelper::setTimezone($this->availability->timezone);
		$bookingDate = $item['fromDate'];
		if($item['fromDate'] != $item['toDate']){
			$bookingDate = $item['toDate'];
		}
		$bookingDate = strtotime($bookingDate);
		$now = strtotime('now');
		if($bookingDate < $now){
			//booking is already expired
			Calendarista_TimeHelper::setTimezone($originalTimezone);
			return false;
		}
		if($this->generalSetting->cancellationPolicy > 0){
			$cancelPolicy = strtotime('+' . $this->generalSetting->cancellationPolicy . ' minutes', $now);
			if($cancelPolicy > $bookingDate){
				//cannot cancel, violating policy
				Calendarista_TimeHelper::setTimezone($originalTimezone);
				return false;
			}
		}
		return true;
	}
	function cancelAppointment($orderId, $bookedAvailabilityId){
		$orderRepo = new Calendarista_OrderRepository();
		$order = $orderRepo->read($orderId);
		if(!$order){
			return;
		}
		$bookedAvailabilityList = $this->bookedAvailabilityRepo->readByOrderId($orderId);
		$this->bookedAvailabilityRepo->updateStatus($bookedAvailabilityId, Calendarista_AvailabilityStatus::CANCELLED);
		Calendarista_GoogleCalendarHelper::updateEvent($bookedAvailabilityId);
		Calendarista_EmailReminderJob::cancelSchedule($orderId);
		//Notify admin that a booking has been cancelled.
		if($this->generalSetting->enableCancelBookingAlert){
			$notification = new Calendarista_NotificationEmailer(array(
				'orderId'=>$orderId
				, 'emailType'=>Calendarista_EmailType::BOOKING_CANCELLED_ALERT
				, 'bookedAvailabilityId'=>$bookedAvailabilityId
			));
			$staffMembers = Calendarista_PermissionHelper::readStaffMembers(2/*include staffmember object*/, $bookedAvailabilityId);
			if($staffMembers && count($staffMembers) > 0){
				foreach($staffMembers as $staff){
					$notification->send($staff['email']);
				}
			}else{
				$notification->send();
			}
		}
		if($this->generalSetting->customerBookingCancelNotification){
			$notification = new Calendarista_NotificationEmailer(array(
				'orderId'=>$orderId
				, 'emailType'=>Calendarista_EmailType::BOOKING_CANCELLED
				, 'bookedAvailabilityId'=>$bookedAvailabilityId
			));
			$notification->send();
		}
	}
    function get_columns(){
        $columns = array(
			'item'=>''
        );
		
        return $columns;
    }
    function get_sortable_columns() {
		//true means its already sorted
        $sortable_columns = array();
        return $sortable_columns;
    }
    
    /**
		@description binds to data
	*/
    function bind() {
        $per_page = 10;
        
        $columns = $this->get_columns();
        $hidden = array();
        $sortable = $this->get_sortable_columns();
        
        $this->_column_headers = array($columns, $hidden, $sortable);
        $currentPage = $this->get_pagenum() - 1;
		if($currentPage){
			$currentPage = $currentPage * $per_page;
		}
		$bookedAvailabilityId = isset($_POST['bookedAvailabilityId']) ? (int)$_POST['bookedAvailabilityId'] : null;
		$orderId = isset($_POST['orderId']) ? (int)$_POST['orderId'] : null;
		if($bookedAvailabilityId){
			$this->cancelAppointment($orderId, $bookedAvailabilityId);
		}
		$userInfo = Calendarista_PermissionHelper::getUserInfo();
		$result = null;
		if($userInfo){
			$orderRepo = new Calendarista_OrderRepository();
			$orderIdList = $orderRepo->readByUserIdOrEmail($userInfo);
			if($orderIdList && count($orderIdList) > 0){
				$bookedAvailabilityRepo = new Calendarista_BookedAvailabilityRepository();
				$result = $bookedAvailabilityRepo->readByOrderIdList(array(
					'orderIdList'=>$orderIdList
					, 'upcoming'=>true
					, 'pageIndex'=>$currentPage
					, 'limit'=>$per_page
				));
			}
		}
		if(!$result || count($result['resultset']) === 0){
			$this->items = array();
			$this->set_pagination_args(array(
				'total_items' => 0,
				'per_page'    => $per_page,
				'total_pages' => 0
			));
			return;
		}
		$total = $result['total'];
        $total_pages = ceil($total / $per_page);
        $this->items = $result['resultset'];
        $this->set_pagination_args(array(
            'total_items' => $total,
            'per_page'    => $per_page,
            'total_pages' => $total_pages
        ));
    }
	function get_table_classes() {
		return array('calendarista-upcoming-appointment-list list-group');
	}
	public function no_items() {
		if(!Calendarista_PermissionHelper::isUserLoggedIn()){
			echo sprintf('<div class="alert alert-warning" role="alert">%s</div>', __('Please login to view your appointments.', 'calendarista'));
			return;
		}
		echo sprintf('<div class="alert alert-warning" role="alert">%s</div>', __('No items found.', 'calendarista'));
	}
}
?>