<?php

namespace DAO;

/**
 * 用户数据层
 */
class DeliveryFormulaModel extends \DAO\AbstractModel {



    /**
     * 表名
     *
     * @var string
     */
    protected $_tableName = 'han_delivery_formula';

    /**
     * 主键
     *
     * @var string
     */
    protected $_primaryKey = 'id';
    public function init(){

    }
    public function getOne($field,$where){
        $this->setDb($this->dbName);
        return $this->db->select($field)->from($this->_tableName)->where($where)->fetchOne();
    }



    public function getDeliveryFormulaByDistince($storeId,$distince,$deliveryFormula){
        if(!$deliveryFormula){
            return false;
        }
        /*$deliveryFormula['state'] == 1 ? $formula = unserialize($deliveryFormula['formula']) : $formula = unserialize($deliveryFormula['simple_formula']);
        if($deliveryFormula['state'] == 1){
            ksort($formula);
            foreach($formula as $key=>$temp){
                if($key*1000>=$distince){
                    return $formula[$key];
                }
            }
        }else{
            foreach($formula as $key=>$temp){
                if($key*1000>=$distince){
                    return $formula[$key];
                }
            }
        }*/
        $formula = unserialize($deliveryFormula['simple_formula']);
        foreach($formula as $key=>$temp){
            if($key*1000>=$distince){
                return $formula[$key];
            }
        }
    }


    /**
     * 获取店铺自提时间段列表
     * @param $store
     * @return array
     */
    public function getBuyerFormulaForCart($store){
        $currentTime = TIMESTAMP;
        $time = date('Y-m-d', $currentTime);
        if ($store['store_start_time'] && $store['store_close_time']) {
            $todayStartTime = strtotime($time . ' ' . $store['store_start_time']);
            $todayEndTime = strtotime($time . ' ' . $store['store_close_time']);
        } else {
            $todayStartTime = $time + \Our\ApiConst::deliveryStartTime;
            $todayEndTime = $time + \Our\ApiConst::deliveryEndTime;
        }
        if($currentTime<$todayStartTime){
            $currentTime = $todayStartTime;
        }
        $return[]=array();
        $time = date('Y-m-d',$currentTime);
        $todayUnixTime = strtotime($time);
        $todayList = $this->getBuyerFormulaList($currentTime,$todayEndTime,\Our\ApiConst::one);
        $isDefault = \Our\ApiConst::zero;
        if($todayList){
            $return[] = array('time'=>$todayUnixTime,'list'=>$todayList);
        }else{
            $isDefault = \Our\ApiConst::one;
        }
        $tommorowStartTime = $todayStartTime + \Our\ApiConst::oneDaySecond;
        $tommorowEndTime = $todayEndTime + \Our\ApiConst::oneDaySecond;
        $tommorowUnixTime = $todayUnixTime + \Our\ApiConst::oneDaySecond;
        $tromorrowList = $this->getBuyerFormulaList($tommorowStartTime,$tommorowEndTime,$isDefault);
        if($tommorowUnixTime){
            $return[]= array('time'=>$tommorowUnixTime,'list'=>$tromorrowList);
        }
        $isDefault = \Our\ApiConst::zero;
        if(!($todayList&&$tromorrowList)){
            $isDefault = \Our\ApiConst::one;
        }
        $nextStartTime = $todayStartTime + \Our\ApiConst::oneDaySecond*2;
        $nextEndTime = $todayEndTime + \Our\ApiConst::oneDaySecond*2;
        $nextUnixTime = $todayUnixTime + \Our\ApiConst::oneDaySecond*2;
        $nextList = $this->getBuyerFormulaList($nextStartTime,$nextEndTime,$isDefault);
        if($tommorowUnixTime){
            $return[]= array('time'=>$nextUnixTime,'list'=>$nextList);
        }
        return $return;
    }

    public function delDeliverFormulaByStoreId($storeId){
        return \Our\RedisHelper::delCachedFunction(\Redis\Db6\DeliveryFormulaRedisModel::getInstance(),array(&$this, 'getOne'),array(),\Our\ApiConst::sevenDaySecond,array($storeId));
    }

    /**
     * 新的配送公式
     * @param $store
     * @param $storeCarts
     * @param $distance
     * @param bool $deliveryFreeFlag
     * @return array
     * @throws \Our\Exception
     */
    public function getDeliveryFormulaForCartNew($store,$storeCarts,$distance,$deliveryFreeFlag=false){
        $delivery_template_ids = array_unique(array_column($storeCarts,'delivery_template_id'));
        $deliveryFormula = \Our\RedisHelper::cachedFunction(\Redis\Db6\DeliveryFormulaRedisModel::getInstance(),array(&$this, 'getOne'),array('*',array('store_id'=>$store['store_id'])),\Our\ApiConst::sevenDaySecond,array($store['store_id']));
        if(!$deliveryFormula){
            return false;
        }
        $formulaList = unserialize($deliveryFormula['formula']);
        $fullFormulaList = array_column($formulaList, 'list', 'template_id');
        $myFormulaList =array_intersect_key($fullFormulaList,array_flip($delivery_template_ids));
        $distanceFormulaList = array();
        foreach($myFormulaList as $tempFormulaList){
            foreach($tempFormulaList as $tempFormula){
                if($tempFormula['distance']=='other'){
                    $distanceFormulaList[] = $tempFormula;
                    break;
                }else{
                    if($distance<(intval($tempFormula['distance'])*\Our\ApiConst::thousand)){
                        $distanceFormulaList[] = $tempFormula;
                        break;
                    }
                }
            }
        }
        $formula = array();
        $halfList = array();
        $oneList = array();
        $twoList = array();
        $dayList = array();
        $otherList = array();
        foreach($distanceFormulaList as $tempFormuala){
            $halfList[] = $tempFormuala['half']?$tempFormuala['half']:$tempFormuala['other'];
            $oneList[] = $tempFormuala['one']?$tempFormuala['one']:$tempFormuala['other'];
            $twoList[] = $tempFormuala['one']?$tempFormuala['two']:$tempFormuala['other'];
            $dayList[] = $tempFormuala['day']?$tempFormuala['day']:$tempFormuala['other'];
            $otherList[] = $tempFormuala['other'];
        }
        $formula['half'] = max($distanceFormulaList);
        $formula['one'] = max($oneList);
        $formula['two'] = max($twoList);
        $formula['day'] = max($dayList);
        $formula['other'] = max($otherList);
        $currentTime =TIMESTAMP;

        $time = date('Y-m-d',$currentTime);
        $todayUnixTime = strtotime($time);
        if($store['store_dis_sta_time']&&$store['store_dis_end_time']){
            $todayStartTime = strtotime($time.' '.$store['store_dis_sta_time']);
            $todayEndTime = strtotime($time.' '.$store['store_dis_end_time']);
        }else{
            $todayStartTime = $time+\Our\ApiConst::deliveryStartTime;
            $todayEndTime = $time+\Our\ApiConst::deliveryEndTime;
        }
        if($todayStartTime>$currentTime){
            $currentTime = $todayStartTime;
        }
        $defaultFee = $formula['half'];
        $return = array();
        $formulaList = $this->getTodayFormulaList($currentTime,$todayEndTime,$formula,$deliveryFreeFlag);
        $tommorowDefault = \Our\ApiConst::zero;
        if(!$formulaList){
            $tommorowDefault = \Our\ApiConst::one;
        }else{
            $defaultFee = $formula['other'];
            $return[]= array('time'=>$todayUnixTime,'list'=>$formulaList);
        }

        $tommorowStartTime = $todayStartTime + \Our\ApiConst::oneDaySecond;
        $tommorowEndTime = $todayEndTime + \Our\ApiConst::oneDaySecond;

        $tommorowUnixTime = $todayUnixTime + \Our\ApiConst::oneDaySecond;
        $tromorrowList = $this->getOtherDayFormulaList($tommorowStartTime,$tommorowEndTime,$formula['other'],$deliveryFreeFlag,$tommorowDefault);
        if($tommorowUnixTime){
            $return[]= array('time'=>$tommorowUnixTime,'list'=>$tromorrowList);
        }
        $nextStartTime = $todayStartTime + \Our\ApiConst::oneDaySecond*2;
        $nextEndTime = $todayEndTime + \Our\ApiConst::oneDaySecond*2;
        $nextUnixTime = $todayUnixTime + \Our\ApiConst::oneDaySecond*2;
        $isDefault = \Our\ApiConst::zero;
        if(!($formulaList&&$tromorrowList)){
            $isDefault = \Our\ApiConst::one;
        }
        $nextList = $this->getOtherDayFormulaList($nextStartTime,$nextEndTime,$formula['other'],$deliveryFreeFlag,$isDefault);
        if($tommorowUnixTime){
            $return[]= array('time'=>$nextUnixTime,'list'=>$nextList);
        }
        if($return){
            return array('timeList'=>$return,'default'=>$defaultFee);
        }
        return $return;

    }

    public function getTodayFormulaList($beginTime,$endTime,$formulaPrice,$deliveryFreeFlag){
        $formulaList = array();
        $initMinute = intval(date('i',$beginTime));
        if($initMinute==0||$initMinute==30){
            $startTime = $beginTime;
        }else{
            if($initMinute<30){
                $startTime = mktime(date('H',$beginTime),30,0,date('m',$beginTime),date('d',$beginTime),date('Y',$beginTime));
            }else if($initMinute<60){
                $startTime = mktime(date('H',$beginTime),60,0,date('m',$beginTime),date('d',$beginTime),date('Y',$beginTime));
            }
        }
        if($startTime+\Our\ApiConst::halfHour<$endTime){
            $interval =\Our\ApiConst::zero;
            for($i=$startTime;$i<$endTime;$i = $i+(\Our\ApiConst::halfHour)){
                $interval += \Our\ApiConst::halfHour;
                $temp = array();
                $temp['time'] = $i;
                $temp['interval'] = \Our\ApiConst::halfHour;
                $temp['isDefault'] = \Our\ApiConst::zero;
                if($interval==\Our\ApiConst::halfHour*1){//半小时内的价格
                    $temp['price'] = $formulaPrice['half'];
                    $temp['isDefault'] = \Our\ApiConst::one;
                }else if($interval<=\Our\ApiConst::halfHour*2){
                    $temp['price'] = $formulaPrice['one'];
                }else if($interval<=\Our\ApiConst::halfHour*4){
                    $temp['price'] = $formulaPrice['two'];
                }else{
                    $temp['price'] = $formulaPrice['day'];
                }
                if($deliveryFreeFlag){
                    $temp['price'] = \Our\ApiConst::zero;
                }
                $temp['price'] = $temp['price']?$temp['price']:\Our\ApiConst::zero;
                $formulaList[] = $temp;
            }
        }
        return $formulaList;
    }

    public function getOtherDayFormulaList($beginTime,$endTime,$price,$deliveryFreeFlag,$isDefault = \Our\ApiConst::zero){
        $formulaList = array();
        $initMinute = intval(date('i',$beginTime));
        if($initMinute==0||$initMinute==30){
            $startTime = $beginTime;
        }else{
            if($initMinute<30){
                $startTime = mktime(date('H',$beginTime),30,0,date('m',$beginTime),date('d',$beginTime),date('Y',$beginTime));
            }else if($initMinute<60){
                $startTime = mktime(date('H',$beginTime),60,0,date('m',$beginTime),date('d',$beginTime),date('Y',$beginTime));
            }
        }
        if($startTime+\Our\ApiConst::halfHour<$endTime){
            for($i=$startTime;$i<$endTime;$i = $i+(\Our\ApiConst::halfHour)){
                $temp = array();
                $temp['time'] = $i;
                $temp['interval'] = \Our\ApiConst::halfHour;
                $temp['price'] = $price?$price:\Our\ApiConst::zero;
                if($deliveryFreeFlag){
                    $temp['price'] = \Our\ApiConst::zero;
                }
                $temp['isDefault'] = $isDefault;
                $isDefault = \Our\ApiConst::zero;
                $formulaList[] = $temp;
            }
        }
        return $formulaList;
    }


    /**
     * 获取自提时间段
     * @param $beginTime
     * @param $endTime
     * @param int $isDefault
     * @return array
     */
    public function getBuyerFormulaList($beginTime,$endTime,$isDefault = \Our\ApiConst::zero){
        $formulaList = array();
        $initMinute = intval(date('i',$beginTime));
        if($initMinute==0||$initMinute==30){
            $startTime = $beginTime;
        }else{
            if($initMinute<30){
                $startTime = mktime(date('H',$beginTime),30,0,date('m',$beginTime),date('d',$beginTime),date('Y',$beginTime));
            }else if($initMinute<60){
                $startTime = mktime(date('H',$beginTime),60,0,date('m',$beginTime),date('d',$beginTime),date('Y',$beginTime));
            }
        }
        if($startTime+\Our\ApiConst::halfHour<$endTime){
            for($i=$startTime;$i<$endTime;$i = $i+(\Our\ApiConst::halfHour)){
                $temp = array();
                $temp['time'] = $i;
                $temp['interval'] = \Our\ApiConst::halfHour;
                $temp['isDefault'] = $isDefault;
                $temp['price'] = \Our\ApiConst::zero;
                $isDefault = \Our\ApiConst::zero;
                $formulaList[] = $temp;
            }
        }
        return $formulaList;
    }


    public function getDeliveryFormulaForCart($store,$distance,$deliveryFreeFlag=false){
        $deliveryFormula = \Our\RedisHelper::cachedFunction(\Redis\Db6\DeliveryFormulaRedisModel::getInstance(),array(&$this, 'getOne'),array('*',array('store_id'=>$store['store_id'])),\Our\ApiConst::sevenDaySecond,array($store['store_id']));
        if(!$deliveryFormula){
            return false;
        }
        //$deliveryFormula['state'] == \Our\ApiConst::one ? $formula = unserialize($deliveryFormula['formula']) : $formula = unserialize($deliveryFormula['simple_formula']);
        $formula = unserialize($deliveryFormula['simple_formula']);
        ksort($formula);
        foreach ($formula as $k=>$v){
            if($k*1000 >= $distance){
                $choosedData = $v;
                //$choosedData['deliver_distance'] = $k;
                break;
            }
        }
        if(!isset($choosedData)){
            return false;
        }
        $deliveryIntval = intval($store['delivery_interval'])>0?intval($store['delivery_interval']):\Our\ApiConst::defaultDeliveryInterval;
        $time = date('Y-m-d',time());
        $todayUnixTime = strtotime($time);
        if($store['store_dis_sta_time']&&$store['store_dis_end_time']){
            $todayStartTime = strtotime($time.' '.$store['store_dis_sta_time']);
            $todayEndTime = strtotime($time.' '.$store['store_dis_end_time']);
        }else{
            $todayStartTime = $time+\Our\ApiConst::deliveryStartTime;
            $todayEndTime = $time+\Our\ApiConst::deliveryEndTime;
        }
        $tommorowStartTime = $todayStartTime + \Our\ApiConst::oneDaySecond;
        $tommorowEndTime = $todayEndTime + \Our\ApiConst::oneDaySecond;
        /*if($deliveryFormula['state'] == \Our\ApiConst::one) {
            $returnData = $this->getCommonFormula($choosedData,$todayStartTime,$todayEndTime,$tommorowStartTime,$tommorowEndTime,$deliveryIntval);
        }else{
            $returnData = $this->getSimpleFormula($choosedData,$todayStartTime,$todayEndTime,$tommorowStartTime,$tommorowEndTime,$deliveryIntval);
        }*/
        $returnData = $this->getSimpleFormula($choosedData,$todayStartTime,$todayEndTime,$tommorowStartTime,$tommorowEndTime,$deliveryIntval);
        if($deliveryFreeFlag&&$returnData){
            $aRplaceMent=array_fill(0,count($returnData),array('price'=>0));
            $returnData=array_replace_recursive($returnData,$aRplaceMent);
        }
        return $returnData;
    }

    /**
     * 获取简易版配送公式
     * @param $choosedData
     * @param $todayStartTime
     * @param $todayEndTime
     * @param $tommorowStartTime
     * @param $tommorowEndTime
     * @param $deliveryIntval
     * @return array
     */
    public function getSimpleFormula($choosedData,$todayStartTime,$todayEndTime,$tommorowStartTime,$tommorowEndTime,$deliveryIntval){
        $currentTime = time();
        $minTime = $choosedData[0]['time']*\Our\ApiConst::oneMinute;
        $minFee =  $choosedData[count($choosedData)-1]['price']*\Our\ApiConst::hundred;
        ksort($choosedData);
        if($currentTime<$todayStartTime){
            $myCurrentStartTime = $todayStartTime;
            $myCurrentEndTime = $todayEndTime;
        }else if(($currentTime+$minTime)>$todayEndTime){//今天无法配送的情况下直接返回明天的配送时间
            $tommorowData = $this->getTomorrowFormulaList($tommorowStartTime,$tommorowEndTime,\Our\ApiConst::oneHour,$minFee,$currentTime);
            $returnData = $tommorowData;
            ksort($returnData);
            foreach($returnData as &$data){
                $data['isDefault'] = \Our\ApiConst::one;
                break;
            }
            return $returnData;
        }else{
            $myCurrentStartTime = $currentTime;
            $myCurrentEndTime = $todayEndTime;
        }
        $tommorowData = $this->getTomorrowFormulaList($tommorowStartTime,$tommorowEndTime,\Our\ApiConst::oneHour,$minFee,$myCurrentStartTime);
        $returnData = array();
        ksort($choosedData);
        $expriseStartTime = \Our\ApiConst::zero;
        //var_dump($choosedData);
        foreach($choosedData as $key=>$temp){
            $tempData = array();
            $expriseStartTime = $myCurrentStartTime+ $temp['time']*\Our\ApiConst::oneMinute;
            if($expriseStartTime<=$myCurrentEndTime){
                $tempData['interval'] = $temp['time']*\Our\ApiConst::oneMinute;
                $tempData['time'] = $myCurrentStartTime + $tempData['interval'];
                $tempData['price'] = $temp['price']*\Our\ApiConst::hundred;
                if($key==2){
                    $tempData['isDefault'] = \Our\ApiConst::one;
                }else{
                    $tempData['isDefault'] = \Our\ApiConst::zero;
                }
                $returnData[] = $tempData;
            }else{
                break;
            }
        }
        $expriseStartTime += $deliveryIntval*\Our\ApiConst::oneMinute;
        if($expriseStartTime<$todayEndTime){
            $expriseData = $this->getTomorrowFormulaList($expriseStartTime,$todayEndTime,$deliveryIntval*\Our\ApiConst::oneMinute,$minFee,$myCurrentStartTime);
            if($expriseData){
                $returnData = array_merge($expriseData,$returnData);
            }
        }
        if($returnData){
            $returnData = array_merge($returnData,$tommorowData);
        }else{
            $returnData = $tommorowData;
        }
        foreach($returnData as $key => $delivery){
            $time[$key] = $delivery['time'];
        }
        array_multisort($time, SORT_ASC, $returnData);
        return $returnData;
    }


    /**
     * 获取常规版配送公式
     * @param $formula
     * @param $todayStartTime
     * @param $todayEndTime
     * @param $tommorowStartTime
     * @param $tommorowEndTime
     * @param $deliveryIntval
     * @return array
     */
    public function getCommonFormula($formula,$todayStartTime,$todayEndTime,$tommorowStartTime,$tommorowEndTime,$deliveryIntval){
        $returnData = array();
        $currentTime = time();
        $minTime = $formula['min_time'] * \Our\ApiConst::oneMinute;
        $minFee = $formula['min_price'] * \Our\ApiConst::hundred;
        $defaultFee = $formula['default_price'] * \Our\ApiConst::hundred;
        if($currentTime<$todayStartTime){
            $myCurrentStartTime = $todayStartTime;
            $myCurrentEndTime = $todayEndTime;
        }else if(($currentTime+$minTime)>$todayEndTime){//今天无法配送的情况下直接返回明天的配送时间
            $tommorowData = $this->getTomorrowFormulaList($tommorowStartTime,$tommorowEndTime,\Our\ApiConst::oneHour,$minFee,$currentTime);
            $returnData = $tommorowData;
            ksort($returnData);
            foreach($returnData as &$data){
                $data['isDefault'] = \Our\ApiConst::one;
                break;
            }
            return $returnData;
        }else{
            $myCurrentStartTime = $currentTime;
            $myCurrentEndTime = $todayEndTime;
        }
        $tommorowData = $this->getTomorrowFormulaList($tommorowStartTime,$tommorowEndTime,\Our\ApiConst::oneHour,$minFee,$myCurrentStartTime);
        $defalutTime = $myCurrentStartTime + $formula['default_time']*\Our\ApiConst::oneMinute;
        $defalutData['time'] = $defalutTime;
        $defalutData['interval'] = $formula['default_time']*\Our\ApiConst::oneMinute;
        $defalutData['price'] = $formula['default_price']*\Our\ApiConst::hundred;
        $defalutData['isDefault'] = \Our\ApiConst::one;
        $returnData[] = $defalutData;
        $earlierTotalPrice = ($formula['max_price']-$formula['default_price'])*\Our\ApiConst::hundred;
        $earlierTimeIntervalNum  = ($formula['default_time'] - $formula['min_time'])/$formula['interval_time'];
        $earlierPrice = round($earlierTotalPrice/$earlierTimeIntervalNum);//更早送达的单个时间间隔单价
        $intervalTimeInSecond = $formula['interval_time']* \Our\ApiConst::oneMinute;
        for($i = \Our\ApiConst::one;$i<=$earlierTimeIntervalNum;$i++){
            if(($defalutTime - $intervalTimeInSecond*$i)>$myCurrentStartTime){
                $temp = array();
                $temp['time'] = $defalutTime - $intervalTimeInSecond*$i;
                $temp['interval']=$temp['time'] - $currentTime;
                $temp['price'] = $defaultFee + $earlierPrice*$i;
                $temp['isDefault'] = \Our\ApiConst::zero;
                $returnData[] =$temp;
            }
        }
        $laterTotalPrice = ($formula['default_price']-$formula['min_price'])*\Our\ApiConst::hundred;
        $laterTimeIntervalNum  = ($formula['max_time']-$formula['default_time'] )/$formula['interval_time'];
        $laterPrice = round($laterTotalPrice/$laterTimeIntervalNum);//更早送达的单个时间间隔单价
        $intervalTimeInSecond = $formula['interval_time']* \Our\ApiConst::oneMinute;
        $maxLastTime = \Our\ApiConst::zero;
        for($j = \Our\ApiConst::one;$j<=$laterTimeIntervalNum;$j++){
            if(($defalutTime + $intervalTimeInSecond*$j)<$myCurrentEndTime){
                $temp = array();
                $maxLastTime = $defalutTime + $intervalTimeInSecond*$j;
                $temp['interval']=$maxLastTime-$currentTime;
                $temp['time'] = $maxLastTime;
                $temp['price'] =  $defaultFee- $laterPrice*$j;
                $temp['isDefault'] = \Our\ApiConst::zero;
                $returnData[] =$temp;
            }
        }
        if($maxLastTime+$deliveryIntval*\Our\ApiConst::oneMinute<$myCurrentEndTime){//超过最大配送时间之后的配送
            $otherReturnData = $this->getTomorrowFormulaList($maxLastTime,$myCurrentEndTime,\Our\ApiConst::oneHour,$minFee,$currentTime);
            if($otherReturnData){
                $returnData = array_merge($returnData,$otherReturnData);
            }
        }
        $returnData = array_merge($returnData,$tommorowData);
        foreach($returnData as $key => $delivery){
            $time[$key] = $delivery['time'];
        }
        array_multisort($time, SORT_ASC, $returnData);
        return $returnData;
    }

    /**
     * 获取超出时间配送公式
     * @param $tommorowStartTime
     * @param $tommorowEndTime
     * @param $deliveryIntval
     * @param $defaultDeliveryMoney
     */
    public function getTomorrowFormulaList($tommorowStartTime,$tommorowEndTime,$deliveryIntval,$defaultDeliveryMoney,$currentTime){
        $return = array();
        for($i=$tommorowStartTime;$i<$tommorowEndTime;$i = $i+($deliveryIntval)){
            $temp = array();
            $temp['time'] = $i;
            $temp['interval'] = $i-$currentTime;
            $temp['price'] = $defaultDeliveryMoney;
            $temp['isDefault'] = \Our\ApiConst::zero;
            $return[] = $temp;
        }
        return $return;
    }


    /**
     * 类实例
     *
     * @var \DAO\UserModel
     */
    private static $_instance = null;

    /**
     * 获取类实例
     *
     * @return \DAO\UserModel
     */
    public static function getInstance($dbName = \Our\DbNameConst::salveDBConnectName) {
        if (!(self::$_instance instanceof self)) {
            self::$_instance = new self($dbName);
        }

        return self::$_instance;
    }

}
