<?php
if ( ! defined( 'ABSPATH' ) ) {
  exit; // Exit if accessed directly.
}


if ( ! class_exists( 'OsDashboardController' ) ) :


  class OsDashboardController extends OsController {

    private $booking;


    function __construct(){
      parent::__construct();

      $this->views_folder = LATEPOINT_VIEWS_ABSPATH . 'dashboard/';
      $this->vars['page_header'] = __('Dashboard', 'latepoint');

    }


		public function pro_agents(){

		}

	  /*
			Index
		*/

    public function index(){
      $this->vars['page_header'] = false;

      ob_start();
      $this->widget_bookings_and_availability_timeline();
      $this->vars['widget_bookings_and_availability_timeline'] = ob_get_clean();

      ob_start();
      $this->widget_daily_bookings_chart();
      $this->vars['widget_daily_bookings_chart'] = ob_get_clean();

      ob_start();
      $this->widget_upcoming_appointments(3);
      $this->vars['widget_upcoming_appointments'] = ob_get_clean();

      $this->set_layout('admin');
      $this->format_render(__FUNCTION__);
    }

    public function widget_upcoming_appointments($limit = 3){
      $agents = new OsAgentModel();
      $services = new OsServiceModel();
      $bookings = new OsBookingModel();
      $locations = new OsLocationModel();

      $selected_agent_id = isset($this->params['agent_id']) ? OsAuthHelper::get_current_user()->check_if_allowed_record_id($this->params['agent_id'], 'agent') : false;
      $selected_service_id = isset($this->params['service_id']) ? OsAuthHelper::get_current_user()->check_if_allowed_record_id($this->params['service_id'], 'service') : false;
      $selected_location_id = isset($this->params['location_id']) ? OsAuthHelper::get_current_user()->check_if_allowed_record_id($this->params['location_id'], 'location') : false;

      $this->vars['upcoming_bookings'] = $bookings->get_upcoming_bookings($selected_agent_id, false, $selected_service_id, $selected_location_id, $limit);

      $this->vars['agents'] = $agents->should_be_active()->filter_allowed_records()->get_results_as_models();
      $this->vars['services'] = $services->should_be_active()->filter_allowed_records()->get_results_as_models();
      $this->vars['locations'] = $locations->should_be_active()->filter_allowed_records()->get_results_as_models();

      $this->vars['selected_agent_id'] = $selected_agent_id;
      $this->vars['selected_service_id'] = $selected_service_id;
      $this->vars['selected_location_id'] = $selected_location_id;


      $this->set_layout('none');
      $this->format_render(__FUNCTION__);
    }



    public function widget_daily_bookings_chart($date_from = false, $date_to = false){
      if($date_from == false){
        $date_from = isset($this->params['date_from']) ? OsWpDateTime::os_createFromFormat('Y-m-d', $this->params['date_from']) : new OsWpDateTime('-1 week');
      }
      if($date_to == false){
        $date_to = isset($this->params['date_to']) ? OsWpDateTime::os_createFromFormat('Y-m-d', $this->params['date_to']) : new OsWpDateTime('now');
      }


			$filter = new \LatePoint\Misc\Filter();
			$filter = OsRolesHelper::filter_allowed_records_from_arguments_or_filter($filter);

      if(!empty($this->params['agent_id'])) $filter->agent_id = $this->params['agent_id'];
      if(!empty($this->params['service_id'])) $filter->service_id = $this->params['service_id'];
      if(!empty($this->params['location_id'])) $filter->location_id = $this->params['location_id'];

			if(!OsRolesHelper::are_all_records_allowed()){
				if(!OsRolesHelper::are_all_records_allowed('agent')) $agent_id = OsRolesHelper::get_allowed_records('agent');
			}



      $daily_bookings = OsBookingHelper::get_total_bookings_per_day_for_period($date_from->format('Y-m-d'), $date_to->format('Y-m-d'), $filter);

      $daily_chart_data = [];
      // fill data array with all the days
      for($day_date=clone $date_from; $day_date<=$date_to; $day_date->modify('+1 day')){
        $daily_chart_data[OsTimeHelper::get_nice_date_with_optional_year($day_date->format('Y-m-d'), false, true)] = 0;
      }
      // update the days with count of bookings
      foreach($daily_bookings as $bookings_for_day){
        $daily_chart_data[OsTimeHelper::get_nice_date_with_optional_year(gmdate( 'Y-m-d', strtotime($bookings_for_day->start_date)), false, true)] = $bookings_for_day->bookings_per_day;
      }

      $this->vars['total_bookings'] = OsBookingHelper::get_stat_for_period('bookings', $date_from->format('Y-m-d'), $date_to->format('Y-m-d'), $filter);
      $this->vars['total_price'] = OsBookingHelper::get_stat_for_period('price', $date_from->format('Y-m-d'), $date_to->format('Y-m-d'), $filter);
      $this->vars['total_duration'] = OsBookingHelper::get_stat_for_period('duration', $date_from->format('Y-m-d'), $date_to->format('Y-m-d'), $filter);
      $this->vars['total_new_customers'] = OsBookingHelper::get_new_customer_stat_for_period($date_from, $date_to, $filter);

      $day_difference = $date_from->diff($date_to);
      $day_difference = ($day_difference->d > 0) ? $day_difference->d : 1;

      $prev_date_from = clone $date_from;
      $prev_date_from->modify('-'.$day_difference.' days');
      $prev_date_to = clone $date_to;
      $prev_date_to->modify('-'.$day_difference.' days');

      $this->vars['prev_total_bookings'] = OsBookingHelper::get_stat_for_period('bookings', $prev_date_from->format('Y-m-d'), $prev_date_to->format('Y-m-d'), $filter);
      $this->vars['prev_total_price'] = OsBookingHelper::get_stat_for_period('price', $prev_date_from->format('Y-m-d'), $prev_date_to->format('Y-m-d'), $filter);
      $this->vars['prev_total_duration'] = OsBookingHelper::get_stat_for_period('duration', $prev_date_from->format('Y-m-d'), $prev_date_to->format('Y-m-d'), $filter);
      $this->vars['prev_total_new_customers'] = OsBookingHelper::get_new_customer_stat_for_period($prev_date_from, $prev_date_to, $filter);


      $agents = new OsAgentModel();
      $services = new OsServiceModel();
      $locations = new OsLocationModel();

      $this->vars['agents'] = $agents->should_be_active()->filter_allowed_records()->get_results_as_models();
      $this->vars['services'] = $services->should_be_active()->filter_allowed_records()->get_results_as_models();
      $this->vars['locations'] = $locations->should_be_active()->filter_allowed_records()->get_results_as_models();

      $this->vars['filter'] = $filter;

      $this->vars['date_from'] = $date_from->format('Y-m-d');
      $this->vars['date_to'] = $date_to->format('Y-m-d');

      $this->vars['daily_bookings_chart_labels_string'] = implode(',', array_keys($daily_chart_data));
      $this->vars['daily_bookings_chart_data_values_string'] = implode(',', array_values($daily_chart_data));

      $pie_labels = [];
      $pie_colors = [];
      $pie_values = [];
      $pie_chart_data = OsBookingHelper::get_stat_for_period('bookings', $date_from->format('Y-m-d'), $date_to->format('Y-m-d'), $filter,'service_id');
      foreach($pie_chart_data as $pie_data){
        $service = new OsServiceModel($pie_data['service_id']);
        $pie_labels[] = $service->name;
        $pie_colors[] = $service->bg_color;
        $pie_values[] = $pie_data['stat'];
      }

      $this->vars['pie_chart_data'] = ['labels' => $pie_labels, 'colors' => $pie_colors, 'values' => $pie_values];

      $this->vars['date_period_string'] = OsTimeHelper::format_date_with_locale(OsSettingsHelper::get_readable_date_format(true, true), $date_from).' - '.OsTimeHelper::format_date_with_locale(OsSettingsHelper::get_readable_date_format(true, true), $date_to);

      $this->set_layout('none');
      $this->format_render(__FUNCTION__);
    }



    public function widget_bookings_and_availability_timeline(){
      $target_date = isset($this->params['date_from']) ? OsWpDateTime::os_createFromFormat('Y-m-d', $this->params['date_from']) : new OsWpDateTime('now');

      $services = new OsServiceModel();
      $agents = new OsAgentModel();
      $locations = new OsLocationModel();

      $agents_models = $agents->should_be_active()->filter_allowed_records()->get_results_as_models();
      $services_models = $services->should_be_active()->filter_allowed_records()->get_results_as_models();
      $locations_models = $locations->should_be_active()->filter_allowed_records()->get_results_as_models();

      $this->vars['services']   = $services_models;
      $this->vars['locations']  = $locations_models;
      $this->vars['agents']     = $agents_models;

      if($services_models && !empty($this->params['service_id'])){
        $selected_service = $services->load_by_id($this->params['service_id']);
      }else{
        $selected_service = false;
      }


      if($locations_models){
        // show all locations option if agent can only be present at one place - because it means he does not have overlapping appointments on the calendar
        $default_location_id = OsSettingsHelper::is_on('one_location_at_time') ? false : $locations_models[0]->id;
        $selected_location_id = !empty($this->params['location_id']) ? $this->params['location_id'] : $default_location_id;
      }else{
        $selected_location_id = false;
      }

      $this->vars['selected_location'] = $selected_location_id ? new OsLocationModel($selected_location_id) : false;
      $this->vars['selected_location_id'] = $selected_location_id;

      $timeblock_interval = OsSettingsHelper::get_default_timeblock_interval();
      $selected_service_id = ($selected_service) ? $selected_service->id : false;

      $this->vars['selected_service'] = $selected_service;
      $this->vars['selected_service_id'] = $selected_service_id;



			// we are using two separate booking requests because the calendar on top has to generate availability timeline,
	    // which can only be generated if we know service to check for. The second booking request is used to retrieve
	    // shared resources for all services and locations (unless specific location is selected)
			$availability_booking_request = new \LatePoint\Misc\BookingRequest(['start_date' => $target_date->format('Y-m-d')]);
			$general_booking_request = new \LatePoint\Misc\BookingRequest(['start_date' => $target_date->format('Y-m-d')]);
			if($selected_location_id){
				$availability_booking_request->location_id = $selected_location_id;
				$general_booking_request->location_id = $selected_location_id;
			}
			if($selected_service){
				$availability_booking_request->service_id = $selected_service->id;
				// TODO add capacity and duration select box and POST params if multiple durations in a service
				$availability_booking_request->duration = $selected_service->duration;
				$timeblock_interval = $selected_service->get_timeblock_interval();
			}

      if(count($agents_models) == 1) {
				$availability_booking_request->agent_id = $agents_models[0]->id;
				$general_booking_request->agent_id = $agents_models[0]->id;
      }

			$settings = ['accessed_from_backend' => true];
			$resources = OsResourceHelper::get_resources_grouped_by_day($general_booking_request, $target_date, $target_date, $settings);
			$availability_resources = OsResourceHelper::get_resources_grouped_by_day($availability_booking_request, $target_date, $target_date, $settings);
			$work_boundaries = OsResourceHelper::get_work_boundaries_for_resources($resources[$target_date->format('Y-m-d')]);
			$work_total_minutes = $work_boundaries->end_time - $work_boundaries->start_time;

      $this->vars['timeblock_interval'] = $timeblock_interval;

      $bookings = [];
			$agent_work_time_periods = [];
      if($agents_models){
        foreach($agents_models as $agent){
					$agent_work_time_periods[$agent->id] = [];
          $args = ['agent_id' => $agent->id];
          if($selected_location_id) $args['location_id'] = $selected_location_id;
					$args['status'] = OsCalendarHelper::get_booking_statuses_to_display_on_calendar();
					$args = OsRolesHelper::filter_allowed_records_from_arguments_or_filter($args);
          $bookings[$agent->id] = OsBookingHelper::get_bookings_for_date($target_date->format('Y-m-d'), $args);
        }
				foreach($availability_resources[$target_date->format('Y-m-d')] as $resource){
					if(isset($agent_work_time_periods[$resource->agent_id])) $agent_work_time_periods[$resource->agent_id] = array_merge($agent_work_time_periods[$resource->agent_id], $resource->work_time_periods);
				}
      }


      $this->vars['agent_work_time_periods'] = $agent_work_time_periods;

			$this->vars['availability_booking_request'] = $availability_booking_request;
			$this->vars['general_booking_request'] = $general_booking_request;

			$agents_resources = [];
			foreach ($agents_models as $agent) {
				$agent_booking_request = clone $availability_booking_request;
				$agent_booking_request->agent_id = $agent->id;
				$daily_resources = OsResourceHelper::get_resources_grouped_by_day($agent_booking_request, $target_date, null, $settings);
				$agents_resources['agent_' . $agent->id] = $daily_resources[$target_date->format('Y-m-d')];
			}
			$this->vars['agents_resources'] = $agents_resources;
			$this->vars['timeline_boundaries'] = OsResourceHelper::get_work_boundaries_for_groups_of_resources($agents_resources);

			$this->vars['work_total_minutes'] = $work_total_minutes;
      $this->vars['work_boundaries'] = $work_boundaries;
      $this->vars['show_day_info'] = OsAuthHelper::is_admin_logged_in();
      $this->vars['target_date_obj'] = $target_date;
      $this->vars['target_date'] = $target_date->format('Y-m-d');
      $this->vars['target_date_string'] = OsTimeHelper::get_readable_date($target_date);

			$this->vars['what_to_show'] = isset($this->params['what_to_show']) ? $this->params['what_to_show'] : 'appointments';


      $today_date = new OsWpDateTime('today');

			if($target_date->format('Y-m-d') == $today_date->format('Y-m-d')){
				$time_now = OsTimeHelper::now_datetime_object();
				$time_now_in_minutes = OsTimeHelper::convert_datetime_to_minutes($time_now);
				if(($time_now_in_minutes<=$work_boundaries->end_time && $time_now_in_minutes>=$work_boundaries->start_time)){
					$this->vars['time_now_label'] = $time_now->format(OsTimeHelper::get_time_format());
					// agents row with avatars and margin below - offset that needs to be accounted for when calculating "time now" indicator position
					$this->vars['time_now_indicator_left_offset'] = ($time_now_in_minutes - $work_boundaries->start_time) / $work_total_minutes * 100;
					$this->vars['show_today_indicator'] = true;
				}else{
					$this->vars['show_today_indicator'] = false;
				}
			}else{
				$this->vars['show_today_indicator'] = false;
			}

      $this->set_layout('none');

      $this->format_render(__FUNCTION__);
    }


  }

endif;