<?php

include_once("server/lib/mod_dbm/package.dbm.php");
include_once("server/class/Pedido.php");
include_once("server/class/PedidosManager.php");
include_once("server/class/WebStatusManager.php");

/**
 * Description of Delivery
 *
 * @author pc
 */
class Delivery {

    public $idDelivery;
    public $deliveryIsLogged = false;
    public $iniciales;
    public $nombre;
    public $passwordHash;
    public $habilitadoHasta;
    public $habilitadoDesde;
    public $localActual;
    public $dao;
    public $lat;
    public $lng;
    public $lastUpdate;

    public function __construct($idDelivery=null) {
        $this->idDelivery = $idDelivery;
        $this->dao = new dbObject();
    }

    public function getId() {
        return $this->idDelivery;
    }

    public function getLocalActual() {
        return $this->localActual;
    }

    public function appValidate($password) {

        $statement = $this->dao->connection->prepare("SELECT * FROM deliverys WHERE id_delivery = ? AND pass_hash = ?");
        $statement->bind_param("ss", $this->idDelivery, $password);
        $statement->execute();

        $result = $statement->get_result();
        if ($d = $result->fetch_array(MYSQLI_BOTH)) {
            $this->iniciales = $d['iniciales'];
            $this->nombre = $d['nombre'];
            $this->habilitadoHasta = $d['habilitado_hasta'];
            $this->habilitadoDesde = $d['habilitado_desde'];
            $this->localActual = $d['local_actual'];
            return true;
        }
        return false;
    }

    public function setIdDeliveryFromToken($token) {

        $statement = $this->dao->connection->prepare("SELECT id_delivery FROM deliverys WHERE current_token = ?");
        $statement->bind_param("s", $token);
        $statement->execute();

        $result = $statement->get_result();
        if ($d = $result->fetch_array(MYSQLI_BOTH)) {
            $this->idDelivery = $d['id_delivery'];
        } else {
            $this->idDelivery = -1;
        }
        return $this->idDelivery;
    }

    private function updateLastLogin() {
        $statement = $this->dao->connection->prepare("UPDATE deliverys SET habilitado_desde = ?, habilitado_hasta=? WHERE id_delivery = ?");
        $statement->bind_param("iis",);
        $statement->execute();
    }

    public function isLogged() {

        $q = sprintf("SELECT current_token, local_actual FROM deliverys WHERE id_delivery = \"%s\" AND habilitado_hasta >= %d",$this->idDelivery,time(),time());
        $result = $this->dao->fetchQuery($q);

        if(is_array($result) && count($result)){
            if(is_null($result[0]['current_token'])){
                $logged = -1;
            } else {
                $logged = (is_null($result[0]['local_actual']))?0:$result[0]['local_actual'];
            }
        } else {
            $logged = -1;
        }
        return $logged;
    }

    public function getPedidosCount(){
        $q = sprintf("SELECT count(*) as pedidos from pedidos WHERE id_delivery = '%s' AND status IN ('PEN','ENC')",$this->idDelivery);
        $result = $this->dao->fetchQuery($q);
        if(is_array($result) && count($result)){
            $pedidos = $result[0]['pedidos'];
        } else{
            $pedidos = 0;
        }
        return $pedidos;
    }

    public function getLastPedidoTimestamp(){
        $q = sprintf("SELECT recogido_timestamp from pedidos WHERE id_delivery = '%s' ORDER BY recogido_timestamp DESC LIMIT 0,1",$this->idDelivery);
        $result = $this->dao->fetchQuery($q);
        if(is_array($result) && count($result)){
            $lastPedidoPick = $result[0]['recogido_timestamp'];
        } else{
            $lastPedidoPick = time();
        }
        return $lastPedidoPick;
    }
   
    public function retrieve() {

        if ($this->idDelivery) {

            $q = sprintf("SELECT * FROM deliverys WHERE id_delivery = '%s'",$this->idDelivery);
            $res = $this->dao->fetchQuery($q);
            if(is_array($res) && count($res)){
                
                $this->idDelivery = $res[0]['id_delivery'];
                $this->iniciales = $res[0]['iniciales'];
                $this->nombre = $res[0]['nombre'];
                $this->habilitadoHasta = $res[0]['habilitado_hasta'];
                $this->habilitadoDesde = $res[0]['habilitado_desde'];
                $this->localActual = $res[0]['local_actual'];
                $this->lat = $res[0]['current_lat'];
                $this->lng = $res[0]['current_lng'];
                $this->lastUpdate = $res[0]['last_update'];
            } else {
                $this->idDelivery = -1;
            }
            return $this->idDelivery;
        } else {
            return false;
        }
    }

    public function retrieveFromToken($token) {

        $statement = $this->dao->connection->prepare("SELECT * FROM deliverys WHERE current_token = ?");
        $statement->bind_param("s", $token);
        $statement->execute();

        $result = $statement->get_result();
        if ($d = $result->fetch_array(MYSQLI_BOTH)) {
            $this->idDelivery = $d['id_delivery'];
            $this->iniciales = $d['iniciales'];
            $this->nombre = $d['nombre'];
            $this->habilitadoHasta = $d['habilitado_hasta'];
            $this->habilitadoDesde = $d['habilitado_desde'];
            $this->localActual = $d['local_actual'];
            $this->lat = $d['current_lat'];
            $this->lng = $d['current_lng'];
            $this->lastUpdate = $d['last_update'];
        } else {
            $this->idDelivery = -1;
        }
        return $this->idDelivery;
    }

    private function registerStop($lat, $lng, $stopTs) {
        $statement = $this->dao->connection->prepare("INSERT INTO bocatti.delivery_stops(delivery_id,stop_ts,lat,lng) VALUES (?,?,?,?)");
        $statement->bind_param("iidd", $this->idDelivery, $stopTs, $lat, $lng);
        $statement->execute();
        $statement->close();
    }

    public function isEnrolled() {
        $isEnrolled = null;
        $q = sprintf("SELECT local_actual FROM deliverys WHERE id_delivery = \"%s\"", $this->idDelivery);
        $res = $this->dao->fetchQuery($q);
        if ((is_array($res) && count($res))) {
            $isEnrolled = ($res[0]['local_actual'] != null);
        }
        return $isEnrolled;
    }

    public function enroll($idLocal,$strict=false, $numeroTarjeta = "1") {
        
        $success = null;
        
        if($strict){
            if(!dismiss($this->idDelivery)){
                return false;
            }
        }
        
        if (!($strict && $this->isEnrolled())) {
            $statement = $this->dao->connection->prepare("UPDATE deliverys SET habilitado_desde = ?, habilitado_hasta=?, local_actual = ?, tarjeta_actual=?  WHERE id_delivery = ?;");
            $desde = time();
            $hasta = $desde + 43200;
            $statement->bind_param("iiiss", $desde, $hasta, $idLocal, $numeroTarjeta, $this->idDelivery);
            $statement->execute();
            $success = ($this->dao->connection->affected_rows === 1);
        } 
        return $success;
    }

    public function dismiss($idDelivery) {

        $updatedDelivery = false;
        
        $statement = $this->dao->connection->prepare("UPDATE deliverys SET habilitado_desde = null, habilitado_hasta=null, current_token=null, last_update = null, local_actual = null WHERE id_delivery = ?;");
        $statement->bind_param("s", $idDelivery);
        $statement->execute();
        //$updatedDelivery = ($this->dao->connection->affected_rows === 1);

        $q = sprintf("SELECT * FROM deliverys WHERE id_delivery = '%s'",$idDelivery);
        $res = $this->dao->fetchQuery($q);
        if(is_array($res) && count($res)){
            $updatedDelivery = (is_null($res[0]['habilitado_desde'])) && is_null($res[0]['habilitado_hasta']) && is_null($res[0]['current_token']) && is_null($res[0]['local_actual']);
        } 

        // Establecer el estado de todos los pedidos que pudiera tener asignados como "SUS"
        $q = sprintf("SELECT * FROM pedidos WHERE id_delivery = '%s' AND status IN (\"PEN\",\"ENC\");",$idDelivery);
        $res = $this->dao->fetchQuery($q);
        if(is_array($res) && count($res)){
            $pedidoManager = new PedidosManager();
            foreach($res as $pedido){
                $pedidoManager->setPedidoStatus($pedido['id_pedido'], "SUS", $idDelivery);
                WebStatusManager::updateStatus($pedido['numero_pedido_bocatti'], "SUS");
            }
        }
        return $updatedDelivery;
    }

    public function updateToken($token, $ver, $from = false) {
        $statement = $this->dao->connection->prepare("UPDATE deliverys SET current_token = ?, habilitado_desde=?, habilitado_hasta=? WHERE id_delivery = ?");
        $validFrom = ($from) ? $from : null;
        $validthru = ($from) ? ($validFrom + 86400) : null;
        $statement->bind_param("siis", $token, $validFrom, $validthru, $this->idDelivery);
        $statement->execute();
        
        $logQ = sprintf("INSERT INTO delivery_login (log_timestamp, log_operation, id_delivery, app_version) VALUES (%d,'%s',%d, '%s')",time(),'LGN',$this->idDelivery,$ver);
        $this->dao->execute($logQ);
    }

    public function logout($token) {
        $statement = $this->dao->connection->prepare("UPDATE deliverys SET current_token = null, habilitado_desde=null, habilitado_hasta=null WHERE id_delivery = ? AND current_token=?");

        $statement->bind_param("ss", $this->idDelivery, $token);
        $statement->execute();
        return $statement->affected_rows;
    }

    public function addPedidos($pedidosArray) {

        if (is_array($pedidosArray) && count($pedidosArray)) {
            $result = true;
            foreach ($pedidosArray as $i => $pedido) {
                $result = $result && $this->addPedido($pedido);
            }
        } else {
            $result = false;
        }
        return $result;
    }

    public function addPedido($pedido) {
        if(($pedido->idLocal == $this->localActual) && !$this->hasPending($pedido->tsPickup)){
            $pObj = new Pedido();
            return ($pObj->persistData($pedido, $this->idDelivery))?0:-1;
        } else {
            return -2;
        }
    }

    public function hasPending($timestamp){
        $q = sprintf("SELECT * FROM pedidos WHERE id_delivery = \"%s\" AND (recogido_timestamp-%s) < 120",$this->idDelivery,$timestamp);
    }
    
    
    public function setCurrentPosition($lat, $lng, $timestamp) {

        $now = time();
        $statement = $this->dao->connection->prepare("SELECT current_lat, current_lng, last_moving_ts FROM deliverys WHERE id_delivery = ?");
        $statement->bind_param("i", $this->idDelivery);
        $statement->execute();
        $result = $statement->get_result();
        if ($d = $result->fetch_array(MYSQLI_BOTH)) {
            $currLat = $d['current_lat'];
            $currLng = $d['current_lng'];
            $lastMovingTs = $d['last_moving_ts'];
            if (GeoUtils::getTheDistance($currLat, $currLng, $lat, $lng) > DISTANCE_THRESHOLD) {
                $updateStatement = $this->dao->connection->prepare("UPDATE deliverys SET current_lat = ?, current_lng = ?, last_update = ?, last_moving_ts=? WHERE id_delivery = ?");
                $updateStatement->bind_param("ddiis", $lat, $lng, $timestamp, $now, $this->idDelivery);
                $updateStatement->execute();
            } else {
                if ($now - $lastMovingTs > STOP_TIME_THRESHOLD) {
                    $this->registerStop($currLat, $currLng, $now);
                }
            }
        }
    }

}
