<?php
/**
 * Shared utils for the sabreScheduler installation profile for Sabre Software
 */

if (!defined('SIMMETRY_UTILS_INCLUDE')) {
  
  define('SIMMETRY_UTILS_INCLUDE', 1);

  define('PROFILE_APP_QMS', 1);
  define('PROFILE_APP_SCHEDULER', 2);

  $simmetryApp = 0;

  /*
   *  Determine which app is being installed
   */
  function which_app() {
    global $simmetryApp;
    if (empty($simmetryApp)) {
      $host = $_SERVER['HTTP_HOST'];
      $simmetryApp =  (False !== stripos($host, 'scheduler')) ? PROFILE_APP_SCHEDULER : PROFILE_APP_QMS;
    }
    return $simmetryApp;
  }

  /*
   *		load_holidays()
   *
   *		calculates the holidays for each year up to 2038
   */

  function _scheduler_load_holidays() {

    // format to use:
    //
    // get_holiday("year", "month", "day_of_week", "week_of_month");
    // get_holiday("year", "month", "day_of_week);    // no 4th field indicates last week of month check
    // format_date("year", "month", "day");


    try {

      //global $user;
      $content = '';

      //$loaded = variable_get('sch_holidays_installed', 0);
      //if ( $loaded ) { 
        //$content = '<div>' . t('US Holidays have already been loaded into the system') . '</div>';
      //}


      $holiday_list = array(
        array(
          'name' => "New Year's Day",
          'func' => '_format_date_parts',
          'parms' => array(0, 1, 1),
        ),
        array(
          'name' => "New Year's Day, observed",
          'func' => '_observed_day',
          'parms' => array(0, 1, 1),
        ),
        array(
          'name' => "Easter",
          'func' => '_calculate_easter',
          'parms' => array(0),
        ),
        array(
          'name' => "Memorial Day, observed",
          'func' => '_get_holiday',
          'parms' => array(0, 5, 1),
        ),
        array(
          'name' => "Independence Day",
          'func' => '_format_date_parts',
          'parms' => array(0,7,4),
        ),
        array(
          'name' => "Independence Day, observed",
          'func' => '_observed_day',
          'parms' => array(0, 7, 4),
        ),
        array(
          'name' => "Labor Day, observed",
          'func' => '_get_holiday',
          'parms' => array(0, 9, 1, 1),
        ),
        array(
          'name' => "Thanksgiving",
          'func' => '_get_holiday',
          'parms' => array(0, 11, 4, 4),
        ),
        array(
          'name' => "Christmas",
          'func' => '_format_date_parts',
          'parms' => array(0, 12, 25),
        ),
      );


      for ($year = (int)date("Y"); $year < 2038; $year++) {
        
        //kpr($holiday_list);
        
        for ( $h=0; $h < count($holiday_list); $h++ ) {

          $holiday_name = $holiday_list[$h]['name'];
          $holiday_list[$h]['parms'][0] = $year;	// set the year into the holiday parms [0] array index
          $holiday_date = call_user_func_array($holiday_list[$h]['func'], $holiday_list[$h]['parms']);

          $exception = new stdClass();

          $exception->simulator_id = 0;  // applies to all sims
          $exception->exception_desc = $holiday_name;
          $exception->allow_override = 1;
          $exception->event = 1;
          $begin_date = $holiday_date . ' 00:00:00';
          $end_date = $holiday_date . ' 23:59:59';
          $exception->begin_timestamp = strtotime($begin_date);
          $exception->end_timestamp = strtotime($end_date);
          $exception->note_text = '';
          $exception->created_date = time();
          $exception->created_by_user = 1;	
          
          $query = db_select('sch_exceptions', 'ex')
                    ->condition('ex.exception_desc', $holiday_name)
                    ->condition('ex.begin_timestamp', $exception->begin_timestamp)
                    ->condition('ex.end_timestamp', $exception->end_timestamp);
          
          $query->fields('ex', array('exception_id'));
          $result = $query->execute();
          
          //kpr($exception);
          
          if ($result->rowCount() == 0) {
            // doesn't exist, create it
            // new record
            if ( False == drupal_write_record('sch_exceptions', $exception)) {
              $msg = "Oops!  Something went wrong storing the exception record.";
              drupal_set_message(t($msg));
            }
            
          } else {
            //kpr("$holiday_name, $year was not saved.");
          }
          
          
        }
      }
      // save the indicator that the holidays have been loaded
      //variable_set('sch_holidays_installed', 1);


      //$content .= "US Holidays have been successfully loaded";
      //return True;
    } catch (Exception $e) {
      watchdog('SIMmetry Utils', 'load_holidays() ' . $e->getMessage(), array(), WATCHDOG_ERROR);
      return False;
    }
  }

  /*  -- used in sabreScheduler.utils.inc
  function _format_date_parts($year, $month, $day) {
      // pad single digit months/days with a leading zero for consistency (aesthetics)
      // and format the date as desired: YYYY-MM-DD by default

      if (strlen($month) == 1) {
          $month = "0". $month;
      }
      if (strlen($day) == 1) {
          $day = "0". $day;
      }
      $date = $year ."-". $month ."-". $day;
      return $date;
  }
  */



  // the following function get_holiday() is based on the work done by
  // Marcos J. Montes: http://www.smart.net/~mmontes/ushols.html
  //
  // if $week is not passed in, then we are checking for the last week of the month
  function _get_holiday($year, $month, $day_of_week, $week="") {
      if ( (($week != "") && (($week > 5) || ($week < 1))) || ($day_of_week > 6) || ($day_of_week < 0) ) {
          // $day_of_week must be between 0 and 6 (Sun=0, ... Sat=6); $week must be between 1 and 5
          return FALSE;
      } else {
          if (!$week || ($week == "")) {
              $lastday = date("t", mktime(0,0,0,$month,1,$year));
              $temp = (date("w",mktime(0,0,0,$month,$lastday,$year)) - $day_of_week) % 7;
          } else {
              $temp = ($day_of_week - date("w",mktime(0,0,0,$month,1,$year))) % 7;
          }

          if ($temp < 0) {
              $temp += 7;
          }

          if (!$week || ($week == "")) {
              $day = $lastday - $temp;
          } else {
              $day = (7 * $week) - 6 + $temp;
          }

          return _format_date_parts($year, $month, $day);
      }
  }

  function _observed_day($year, $month, $day) {
      // sat -> fri & sun -> mon, any exceptions?
      //
      // should check $lastday for bumping forward and $firstday for bumping back,
      // although New Year's & Easter look to be the only holidays that potentially
      // move to a different month, and both are accounted for.

      $dow = date("w", mktime(0, 0, 0, $month, $day, $year));

      if ($dow == 0) {
          $dow = $day + 1;
      } elseif ($dow == 6) {
          if (($month == 1) && ($day == 1)) {    // New Year's on a Saturday
              $year--;
              $month = 12;
              $dow = 31;
          } else {
              $dow = $day - 1;
          }
      } else {
          $dow = $day;
      }

      return _format_date_parts($year, $month, $dow);
  }


  function _calculate_easter($y) {
      // In the text below, 'intval($var1/$var2)' represents an integer division neglecting
      // the remainder, while % is division keeping only the remainder. So 30/7=4, and 30%7=2
      //
      // This algorithm is from Practical Astronomy With Your Calculator, 2nd Edition by Peter
      // Duffett-Smith. It was originally from Butcher's Ecclesiastical Calendar, published in
      // 1876. This algorithm has also been published in the 1922 book General Astronomy by
      // Spencer Jones; in The Journal of the British Astronomical Association (Vol.88, page
      // 91, December 1977); and in Astronomical Algorithms (1991) by Jean Meeus. 

      $a = $y%19;
      $b = intval($y/100);
      $c = $y%100;
      $d = intval($b/4);
      $e = $b%4;
      $f = intval(($b+8)/25);
      $g = intval(($b-$f+1)/3);
      $h = (19*$a+$b-$d-$g+15)%30;
      $i = intval($c/4);
      $k = $c%4;
      $l = (32+2*$e+2*$i-$h-$k)%7;
      $m = intval(($a+11*$h+22*$l)/451);
      $p = ($h+$l-7*$m+114)%31;
      $EasterMonth = intval(($h+$l-7*$m+114)/31);    // [3 = March, 4 = April]
      $EasterDay = $p+1;    // (day in Easter Month)

      return _format_date_parts($y, $EasterMonth, $EasterDay);
  }

  /////////////////////////////////////////////////////////////////////////////
  // end of calculation functions; place the dates you wish to calculate below
  /////////////////////////////////////////////////////////////////////////////

}


?>






