<?php 
require_once("initializer.php");

class DatabaseObject {

  protected static $table_name;
  private static $db_fields;
  protected static $exclu_fields;
    
        // Common Database Methods
        public static function find_all($Consum="") {
         // error_log(print_r("SELECT ".static::Columns_Select()." FROM ".static::$table_name ,true)); 
        //if Consum is MenuDishes we change the query
        if ($Consum=="SideDishes" || $Consum=="MenuDishes") {
            $day= date('l');
        // error_log(print_r("ADDING FUNCTIONALITY" ,true));
        // error_log(print_r($day,true));
        return static::find_by_sql("SELECT ".static::Columns_Select()." FROM ".static::$table_name." WHERE `AvailableOn` LIKE '%".$day."%' AND `ShowOnMenu`='true'" ,$Consum);

        } elseif ($Consum=="Staff"){

          return static::find_by_sql("SELECT ".static::Columns_Select()." FROM ".static::$table_name. " WHERE `Blocked`='No'","" );

        }else {
          return static::find_by_sql("SELECT ".static::Columns_Select()." FROM ".static::$table_name,$Consum);


        }
      

      }

      public static function find_all_Admin($Consum="") {
        // error_log(print_r("SELECT ".static::Columns_Select()." FROM ".static::$table_name ,true)); 
       //if Consum is MenuDishes we change the query
       
         return static::find_by_sql("SELECT ".static::Columns_Select()." FROM ".static::$table_name,$Consum);


      

     }



    

      
      public static function find_by_id($id=0, $com="") {
        //self::Get_Object_Fields ()
        $result_array = static::find_by_sql("SELECT ".static::Columns_Select()." FROM ".static::$table_name." WHERE id={$id} LIMIT 1",$com);
            return !empty($result_array) ? array_shift($result_array) : false;
      }


      public static function Columns_Select() {
        static::Get_Object_Fields ();

        $statement = "";
        
           foreach(static::$db_fields as $name) {
               if(!in_array($name, static::$exclu_fields)) {
                   if($statement == "")
                       $statement = $name;
                   else
                       $statement .= "," . $name;
               }
           }
           //echo  join(", ", static::$db_fields);
          // error_log(print_r($statement ,true));
           //join(", ", array_keys($attributes))
           return $statement;
      }

    

    public static function Get_Object_Fields () {
      global $database;
     // $sql = "SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='".static::$table_name."'";
      //$sql = "SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='Staff'";
      //$sql = "SHOW COLUMNS FROM `".static::$table_name."`";
      $sql = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='".static::$table_name."'";
      //error_log( print_R($sql,TRUE) );
     //$sql = "SHOW FIELDS FROM ".static::$table_name."";
     
      // $sql = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='".static::$table_name."' AND COLUMN_NAME NOT LIKE \"id\"";
      
      //SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='Staff' AND COLUMN_NAME NOT LIKE "id"
      if (static::$db_fields == null){
        $result_set = $database->query($sql);
       // error_log( print_R($result_set,TRUE) );
        $i=0;
        static::$db_fields=array();
        while ($row = mysqli_fetch_assoc($result_set)){
         // static::$db_fields[$row["COLUMN_NAME"]] = "";
         static::$db_fields[$i] = $row["COLUMN_NAME"];
          ++$i;
        }
  
        return  static::$db_fields;

      }else { return  static::$db_fields;}
     
     
     // error_log( print_R(mysqli_fetch_assoc($result_set),TRUE) );

      
    }
      
      public static function find_by_sql($sql="",$Consum) {
        global $database;
        $result_set = $database->query($sql);
      // error_log( print_R($sql,TRUE) );
        $object_array = array();
        while ($row = $database->fetch_array($result_set)) {
          $object_array[] = static::instantiate($row, $Consum);
        }
       // error_log( print_R($object_array,true) );
        return $object_array;
      }
    
        public static function count_all() {
          global $database;
          $sql = "SELECT COUNT(*) FROM ".self::$table_name;
        $result_set = $database->query($sql);
          $row = $database->fetch_array($result_set);
        return array_shift($row);
        }
    
        private static function instantiate(&$record,&$Consum) {
            // Could check that $record exists and is an array

        $classCalled = get_called_class ();
        $object = new  $classCalled;
            // Simple, long-form approach:
            // $object->id 				= $record['id'];
            // $object->username 	= $record['username'];
            // $object->password 	= $record['password'];
            // $object->first_name = $record['first_name'];
            // $object->last_name 	= $record['last_name'];

            // More dynamic, short-form approach:
            foreach($record as $attribute=>$value){
              if($object->has_attribute($attribute)) {
                $object->$attribute = $value;
              }
            }

            //before returning obj, we set the consummale or 
            //addtion or choises bes on $Consum Var

            switch($Consum) {
              case 'SideDishes' : 
              $ListConsumable = new Consumables ("Blank");
              //$sql = 'SELECT * FROM `Consumables` WHERE `Dish_id`=8 AND`Dish_Type`="SideDish"';
              $sql = "SELECT * FROM Consumables WHERE Dish_id='".$object->id."' AND Dish_Type ='SideDish'";
              $object->Consumables = $ListConsumable ->find_by_sql($sql, "");
              break;

              case 'Customer' : 

              // $sql = "SELECT `id` FROM `Orders` WHERE `Cash`= 'PAID' AND `Customer_id`=".$object->id;

              // error_log( print_R($sql ,true) );

              // $orders = Orders::find_by_sql($sql,"");

              // $object->OrdersByCustomer =  sizeof($orders); 

              // $object->ConsumedbyCustomer = [];
              
              

              // foreach($orders as $attribute=>$value){
              //   //error_log( print_R($value->id ,true) );
              //   //OrdersInfo::findDishInfo($value->id);
              //   $object->ConsumedbyCustomer =  array_merge($object->ConsumedbyCustomer,OrdersInfo::getDishforUser($value->id));
           
              // }
              

              //error_log( print_R("SETTING B",true) );
              //$sql = 'SELECT * FROM `Consumables` WHERE `Dish_id`=8 AND`Dish_Type`="SideDish"';
              // $sql = "SELECT `id` FROM `Orders` WHERE `Customer_id`=".$object->id;

              // $Orders = find_by_sql($sql, "");

              // $object->OrdersByCustomer = $Orders;

              //$object->Consumables = $ListConsumable ->find_by_sql($sql, "");


              // $ListConsumable = new Consumables ("Blank");
              // //$sql = 'SELECT * FROM `Consumables` WHERE `Dish_id`=8 AND`Dish_Type`="SideDish"';
              // $sql = "SELECT * FROM Consumables WHERE Dish_id='".$object->id."' AND Dish_Type ='SideDish'";
              // $object->Consumables = $ListConsumable ->find_by_sql($sql, "");
              break;

              case 'SettingReviews':
               $object->ClientName = Customer::GetCustomerName ($object->User_id) ;
               $object->Package_Name= Packages::FindPackName ($object->Package_id) ;

              break;


            
              case 'PackagesList':
               // $object->DaysLefts = Packages::findBusPackages( $object->id);
              
                // $now = date(); // or your date as well
                // $your_date = strtotime($object->Valid_Until);
                // $datediff = strtotime($now) - $your_date;
                $earlier = new DateTime( );
                $later = new DateTime($object->Valid_Until); 
                $object->DaysLeft =   $later->diff($earlier)->format("%a");
                $object->Imgs = PackIMG::FindPackageImge ($object->Bus_id, $object->id);

                $object->CostUI = explode(".", $object->Cost );


           
              break;

              case 'myItineraryPack':
                $object->Business_Name = Business::getBUS_Name ($object->Bus_id);
                $object->BusLocation = Business::getLocation ($object->Bus_id);
                $object->BusLogo = Business::getBUS_Logo ($object->Bus_id);
                $object->Imgs = PackIMG::FindPackageImge ($object->Bus_id, $object->id);
                $object->Cost = Packages::GetPackCost ($object->Package_id);
                $object->BusinessDetails = Business::find_by_id ($object->Bus_id);
                $object->Category = Packages::FindCategory ($object->Package_id);
                $object->PackName = Packages::FindPackName ($object->Package_id);


              break;


          

            case 'Reviewing':
                $object->Business_Name = Business::getBUS_Name ($object->Bus_id);
                $object->BusLocation = Business::getLocation ($object->Bus_id);
                $object->BusLogo = Business::getBUS_Logo ($object->Bus_id);
                $object->PackName = Packages::FindPackName ($object->Package_id);

   
            break;
              

              case 'SuggestedPack':
                $object->Business_Name = Business::getBUS_Name ($object->Bus_id);
                $object->BusLocation = Business::getLocation ($object->Bus_id);
                $object->BusLogo = Business::getBUS_Logo ($object->Bus_id);
                $object->Imgs = PackIMG::FindPackageImge ($object->Bus_id, $object->id);


              
              break;
			  
			  case 'Highlights_logo':
			                 $object->Logo   = Business::Get_Logo($object->Bus_ID);

			               break;

              case 'chatting':
                $object->Service  = Packages::FindPackName ($object->Package_id);

              break;

              case 'FormatPackages':
			  $pack = Packages::findBusPackages( $object->id);
			                  if (count($pack) > 0) {
			                $object->Packages =  $pack;
			                $tempDL = max_attribute_in_array($object->Packages, "DaysLeft");
			                $object->DayLeft =  $tempDL ==false ? '0' :  $tempDL;

			                $object->Imgs   =[];
			                //Merging Packages Images 
			                foreach ( $object->Packages as  $value) {
			                  array_push($object->Imgs, $value->Imgs );
			               // $object->Imgs   =[];
			                }
			                $object->Imgs = array_merge(...$object->Imgs);
			                $object->PackUI = Business::RandonCTA(sizeof($object->Packages));
			                $object->UserCTA   = Business::UserCTA($object->Category);
			               $object->Check_Pupular   = Business::checkPopular($object->id);
			               $object->Total_Reviews   = Reviews::TotalReviews($object->id);
			               $object->Business_Stars   = Reviews::BusinessStarts($object->id);

			                  } else {
			                    $object->Empty = true;
								$object->Packages = [];
								unset($object);
			                  }
               


             
            


               
              


              //we should include reviews and other goodies here
              // $object->OrderDetails =OrdersInfo::findDishInfo($object->id, "Chef") ;
              // $object->NumberOfItems = sizeof( $object->OrderDetails); ;
 
              break;

            
              case 'Delivery_Chef':

              $object->StaffName = Staff::GetStaffName( $object->APEX_Staff_ID);
              $object->OrderDetails =OrdersInfo::findDishInfo($object->id, "Chef") ;
              $object->NumberOfItems = sizeof( $object->OrderDetails); 

              break;

              case 'Reservations':
              //$object->setProperties();

              $object->ClientName = Customer::GetCustomerName ($object->Customer_id) ;
              $object->year = date('Y', strtotime($object->DatePassed));
              $object->month = date('m', strtotime($object->DatePassed))-1;
              $object->date = date('d', strtotime($object->DatePassed));
 
              break;

               // ...etc...
          }

            // if ($Consum=="SideDishes"){
            //   $ListConsumable = new Consumables ("Blank");
            //   //$sql = 'SELECT * FROM `Consumables` WHERE `Dish_id`=8 AND`Dish_Type`="SideDish"';
            //   $sql = "SELECT * FROM Consumables WHERE Dish_id='".$object->id."' AND Dish_Type ='SideDish'";
            //   $object->Consumables = $ListConsumable ->find_by_sql($sql);
            // }


            return $object;
        }
        
        private function has_attribute($attribute) {
          // We don't care about the value, we just want to know if the key exists
          // Will return true or false
          return array_key_exists($attribute, $this->attributes());
        }
    
        protected function attributes() { 
            // return an array of attribute names and their values
           // echo "seeting attribute <br/>";
           static::Get_Object_Fields ();
          $attributes = array();
          foreach( static::$db_fields as $field) {
            if(!property_exists($this, $field)) {
              $attributes[$field] = $this->$field;
            }else { $attributes[$field] = $this->$field;}
              
         
          }
          return $attributes;
        }

        //extended classes
        
        
        protected function sanitized_attributes() {
          global $database;
          $clean_attributes = array();
          // sanitize the values before submitting
          // Note: does not alter the actual value of each attribute
          //error_log( print_R($this ,FALSE) );
          $objectPassed = $this;
          foreach($objectPassed as $key => $value){
            //error_log( print_R($value,FALSE) );
            // /$clean_attributes[$key] = $database->escape_value($value);
              // /$clean_attributes[$key] = $database->escape_value($value);
              if (isset($value) && !empty($value)) {
                //error_log( print_R($value." =".$key ,TRUE) );
                //$clean_attributes[$key] =  $value;
                //error_log( print_R("SANAITIZING" ,TRUE) );
                  $clean_attributes[$key] =  $value;
  
              }
          
          }
          return $clean_attributes;
        }
        
        public function save() {
          // A new record won't have an id yet.
          error_log( print_R("in save DB Obj",true) );
          return $this->id != "" ? $this->update() : $this->create();
        }

        public static function AddToTotal ($id="", $total="") {
          global $database;
          $sql = "UPDATE ".static::$table_name." SET `Total`=`Total`+".$total."  WHERE id=".$id." ";
            $result = $database->query($sql);
      // UPDATE `Orders` SET `Total`=`Total`+1 WHERE id=".$id." 
      
        }

        public static function Increase_Used_by( $id=""){
          global $database;
          $sql = "UPDATE ".static::$table_name." SET `Used_by`=`Used_by`+1 WHERE id=".$id." ";
          $result = $database->query($sql);
        }

        public static function Decrease_Used_by( $id=""){
          global $database;
          $sql = "UPDATE ".static::$table_name." SET `Used_by`=`Used_by`-1 WHERE id=".$id." ";
          $result = $database->query($sql);
        }

        public static function Last_Consumed ($id="") {
          global $database;
          $sql = "UPDATE ".static::$table_name." SET `Last_Consumed`=NOW() WHERE id=".$id." ";
          $result = $database->query($sql);

        }





        public static function DeleteFromConsumable ($Dish_id="", $Dish_type="") {
          
          global $database;
          $Get_Stock_ID_sql = "SELECT `Stock_id` FROM `Consumables` WHERE `Dish_id`=".$Dish_id." AND `Dish_Type`='".$Dish_type."' ";
          
          //we need to implement Decrease_Used_by on each stock use by dish
          //We first find by sql
          $dishConsumables = Consumables::find_by_sql($Get_Stock_ID_sql,"");
 
          foreach($dishConsumables as $key => $value) {
            Stock::Decrease_Used_by($value->Stock_id);
          
        }

          $Delete_sql = "DELETE FROM `Consumables` WHERE `Dish_id`=".$Dish_id." AND `Dish_Type`='".$Dish_type."' ";
          
          $database->query($Delete_sql);
        }
        
        public function create() {
          error_log( print_R("in create",true) );
             global $database;
            // Don't forget your SQL syntax and good habits:
            // - INSERT INTO table (key, key) VALUES ('value', 'value')
            // - single-quotes around all values
            // - escape all values to prevent SQL injection
            $attributes = $this->sanitized_attributes();
            //echo join(", ", $attribute_pairs);
          $sql = "INSERT INTO ".static::$table_name." (";
            $sql .= join(", ", array_keys($attributes));
          $sql .= ") VALUES ('";
            $sql .= join("', '", array_values($attributes));
            $sql .= "')";
            error_log( print_R( ".esat" .$sql,true) );
            error_log( print_R( ".esat" .$sql,true) );
         
          if($database->query($sql)) {
            $this->id = $database->insert_id();
            return true;
          } else {
            error_log( print_R("chiking errorre sending",true) );
          error_log( print_R(  $database,true) );
            return false;
          }
        }
    
        public function update() {
          global $database;
            // Don't forget your SQL syntax and good habits:
            // - UPDATE table SET key='value', key='value' WHERE condition
            // - single-quotes around all values
            // - escape all values to prevent SQL injection
            $attributes = $this->sanitized_attributes();
            $attribute_pairs = array();
            
            foreach($attributes as $key => $value) {
              $attribute_pairs[] = "{$key}='{$value}'";
            }
           // error_log( print_R( $attribute_pairs,FALSE) );find_by_id
           //echo "see the ide here >>>". join(", ", $attribute_pairs);
          // error_log( print_R($attribute_pairs,FALSE) );
            $sql = "UPDATE " .static::$table_name. " SET ";
            $sql .= join(", ", $attribute_pairs);
            $sql .= " WHERE id=".$this->id;
            //echo $sql;
            // error_log( print_R("udating function",true) );
            // error_log( print_R($attributes,true) );
            // error_log( print_R($attribute_pairs,true) );

            // error_log( print_R($sql,true) );
          $database->query($sql);
          return ($database->affected_rows() == 1) ? true : false;
        }
    
        public function delete() {
            global $database;
            // Don't forget your SQL syntax and good habits:
            // - DELETE FROM table WHERE condition LIMIT 1
            // - escape all values to prevent SQL injection
            // - use LIMIT 1
          $sql = "DELETE FROM ".static::$table_name;
          $sql .= " WHERE id=". $database->escape_value($this->id);
          $sql .= " LIMIT 1";
          // $database->query($sql);
          // $fff=$database->affected_rows();
          // error_log( print_R($fff,true) );
          return  $database->query($sql);
        
            // NB: After deleting, the instance of Staff still 
            // exists, even though the database entry does not.
            // This can be useful, as in:
            //   echo $user->first_name . " was deleted";
            // but, for example, we can't call $user->update() 
            // after calling $user->delete().
        }
    
    }

   

  
    

?>

