<?php
namespace Business\Goods;
/**
 * User: liuyuzhen
 * Date: 2018/5/29
 * Time: 10:20
 * Description:
 */
class GoodsClassServiceModel extends \Business\AbstractModel{


    /**
     * 获取平台首页推荐一级分类
     */
    public function getIndexGoodsClasses($where){
        $goodsClasses = $this->getPlatformGoodsClass($where);
        $totalCount = count($goodsClasses);
        if($totalCount <= \Our\ApiConst::maxIndexGoodsCount){
            $returnGoodsClasses = $goodsClasses;
        }else{
            $returnGoodsClasses = array_slice($goodsClasses,\Our\ApiConst::zero,\Our\ApiConst::nine);
        }
        return array('totalCount'=>$totalCount,'classes'=>$returnGoodsClasses);

    }

    /**
     * 获取当前城市有效签约分类列表
     * @throws \Our\Exception
     */
    public function getSignClassesByCityCode($cityCode){
        $qmStoreClassCon['city_code'] = $cityCode;
        $qmStoreClassCon['is_charged'] = \Our\ApiConst::one;
        $qmStoreClassCon['class_style'] = \Our\ApiConst::signClassStyle;
        $storeField = 'gc_id,sign_scope,gc_parent_id,store_id';

        $qmStoreClassDao = \DAO\QmStoreClassModel::getInstance();
        $signStoreClasses = \Our\RedisHelper::cachedFunction(\Redis\Db6\QmStoreClassRedisModel::getInstance(),array(&$qmStoreClassDao, 'getStoreClasses'),array($qmStoreClassCon,$storeField),\Our\ApiConst::oneHour,array($cityCode));
        return $signStoreClasses;
    }

    public function getHomeIndexGoodsClasses($where){
        $allClasses = $this->getPlatformGoodsClass($where);
        if($allClasses){
            $totalCount = count($allClasses);
            if($totalCount <= \Our\ApiConst::maxHomeIndexClassesCount){
                $returnCalsses = $allClasses;
            }else{
                $returnCalsses = array_slice($allClasses,\Our\ApiConst::zero,\Our\ApiConst::lessHomeIndexClassesCount);
            }
            return array(
                'totalCount'=>$totalCount,
                'classes'=>$returnCalsses
            );
        }else{
            return array('totalCount'=>\Our\ApiConst::zero);
        }
    }
    /**
     * 获取平台全部一级分类
     * @param $where
     * @return array
     * @throws \Our\Exception
     */
    public function getPlatformGoodsClass($where){

        //验证参数
        $addressDao = \DAO\AddressModel::getInstance();
        $validFlag = $addressDao->getValidAddress($where);
        if(!$validFlag){
            \Error\ErrorModel::throwException($addressDao->errorCode);
        }
        //获取当前城市可用签约分类
        $signStoreInfo = $this->getSignStoreInfo($where);

        $signStoreIds = $signStoreInfo['signStoreIds'];//当前位置签约店铺ID
        $signParentClassIds = $signStoreInfo['signParentClassIds'];//当前位置签约分类对应一级分类
        $classIds = array();
        if($signParentClassIds){
            $classIds = $signParentClassIds;
        }
        //当前城市可为当前经纬度提供服务的店铺
        $serviceStoreIds = $this->getServiceStoreIds($where);
        if($serviceStoreIds&&$signStoreIds){
            $serviceStoreIds = array_diff($serviceStoreIds,$signStoreIds);
        }

        $serviceParentClassIds = $this->getServiceStoreClasses($serviceStoreIds);
        if($serviceParentClassIds){
            $classIds = array_merge($serviceParentClassIds,$classIds);
        }
        //获取可快递店铺对应分类

        /*
        $expressClassIds = $this->getExpressStoreClasses($where);
        if($expressClassIds){
            $classIds = array_merge($expressClassIds,$classIds);
        }
        */
        $classIdKeys = array_flip($classIds);
        $goodsClassDao = \DAO\GoodsClassModel::getInstance();
        $parentClasses = $goodsClassDao->getParentClasses();
        $temp =array_diff_key($parentClasses,$classIdKeys);
        if($temp){
            $returnClasses = array_diff_key($parentClasses,$temp);
        }else{
            $returnClasses = $parentClasses;
        }
        $returnClasses = array_values($returnClasses);
        return $returnClasses;

    }


    /**
     * 获取快递店铺对应一级分类
     * @param $where
     * @return array|bool
     */
    public function getExpressStoreClasses($where){
        $field = 'distinct(gc_parent_id) as gc_parent_id';
        $expressClasses = $this->getExpressStoresClasses($where['cityCode'],$field);
        if($expressClasses){
            $expressClassIds = array_column($expressClasses,'gc_parent_id');
            return $expressClassIds;
        }
        return false;
    }

    /**
     * 获取服务店铺所有在经营的一级分类
     * @param $serviceStoreIds
     * @return array
     * @throws \Our\Exception
     */
    public function getServiceStoreClasses($serviceStoreIds){
        if(!$serviceStoreIds){
            return false;
        }
        $serviceWhere = 'is_charged = 1';
        if($serviceStoreIds){
            $serviceWhere .= " and store_id in (".implode(",",$serviceStoreIds).") ";
        }
        $field = 'distinct(gc_parent_id) as gc_parent_id';
        $qmStoreClassDao = \DAO\QmStoreClassModel::getInstance();

        $serviceParentClasses = \Our\RedisHelper::cachedFunction(\Redis\Db6\QmStoreClassRedisModel::getInstance(),array(&$qmStoreClassDao, 'getStoreClasses'),array($serviceWhere,$field),\Our\ApiConst::oneHour);
        if($serviceParentClasses){
            foreach($serviceParentClasses as $class){
                $serviceParentClassIds[] = $class['gc_parent_id'];
            }
            return array_column($serviceParentClasses,'gc_parent_id');
        }
        return false;
    }

    public function getServiceStoreIds($where){

        $storeDao = \DAO\StoreModel::getInstance();
        $storeList = $storeDao->getStoresByCityCode($where['cityCode']);
        $serviceStoreIds = array();
        if($storeList){
            foreach ($storeList as $key=>$store){
                $result =\Store\StoreUtil::getInstance()->checkAddressInServiceArea(array('lng'=>$where['lng'],'lat'=>$where['lat']),$store['store_id']);
                if($result){
                    $serviceStoreIds[] = $store['store_id'];
                }
            }
        }
        if($serviceStoreIds){
            $position['lat'] = $where['lat'];
            $position['lng'] = $where['lng'];
            $position['cityCode'] = $where['cityCode'];
            ksort($position);
            $storeRedis = \Redis\Db6\StoreRedisModel::getInstance();
            $serviceStoreKey = \Our\NameConst::serviceStoreIdsPrefix.crc32(serialize($position));
            $storeRedis->update($serviceStoreKey,$serviceStoreIds,\Our\ApiConst::oneHour);
            return $serviceStoreIds;
        }
        return false;
    }

    public function getSignStoreInfo($where){
        $lat = $where['lat'];
        $lng = $where['lng'];
        $cityCode = $where['cityCode'];

        $storeDao = \DAO\StoreModel::getInstance();
        $signStoreClasses = $this->getSignClassesByCityCode($cityCode);
        if($signStoreClasses){
            $returnClass = array();
            $newStoreIds = array();
            foreach($signStoreClasses as $signClass){
                $inAreaFlag = \Our\CommonExtension::locationInArea($lat,$lng,$signClass['sign_scope']);
                //判断签约分类是否可以为当前用户提供服务,并且记录这些店铺对应的store_id
                if($inAreaFlag){
                    $store =$storeDao->getStoreInfoCache($signClass['store_id']);
                    $class_distance  = \Our\CommonExtension::getDistance($lat,$lng,$store['store_latitude'],$signClass['store_latitude'],1);
                    $class = $signClass;
                    $class['class_distance'] = $class_distance;
                    $returnClass[$class_distance] = $class;
                    if(!($newStoreIds&&in_array($signClass['store_id'],$newStoreIds))){
                        $newStoreIds[] = $signClass['store_id'];
                    }

                }
            }
            ksort($returnClass);

            $signParentClassIds = array_unique(array_column($returnClass,'gc_parent_id'));
            //$signStoreIds = array_unique(array_column($returnClass,'store_id'));
            $signStoreIds = $newStoreIds;

            //将当前位置对应签约店铺存入缓存
            $position['lat'] = $where['lat'];
            $position['lng'] = $where['lng'];
            $position['cityCode'] = $where['cityCode'];
            ksort($position);
            $storeRedis = \Redis\Db6\StoreRedisModel::getInstance();
            if($signStoreIds){
                $signStoreKey = \Our\NameConst::signStoreIdsPrefix.crc32(serialize($position));
                $storeRedis->update($signStoreKey,$signStoreIds,\Our\ApiConst::oneHour);
            }
            return array(
                'signParentClassIds'=>$signParentClassIds,
                'signStoreIds'=>$signStoreIds
            );
        }
        return false;
    }

    /**
     * 获取当前城市对应可快递店铺对应的店铺分类
     * @param $cityCode
     * @param string $field
     * @throws \Our\Exception
     */
    public function getExpressStoresClasses($cityCode,$field = '*'){

        //获取当前城市可用签约分类
        $storeDao = \DAO\StoreModel::getInstance();
        $currentCityExpressStores = $storeDao->getExpressStores('store_id');

        $qmStoreClassDao = \DAO\QmStoreClassModel::getInstance();

        if($currentCityExpressStores){
            $expressStoreIds = array_column($currentCityExpressStores,'store_id');
            //$expressStoreIds = array_keys($currentCityExpressStores);
            if($expressStoreIds){
                $storeClassWhere = ' is_charged = 1 and store_id in ('.implode(',',$expressStoreIds).') ';
                //var_dump($currentCityExpressStores);exit;
                $result = \Our\RedisHelper::cachedFunction(\Redis\Db6\QmStoreClassRedisModel::getInstance(),array(&$qmStoreClassDao, 'getStoreClasses'),array($storeClassWhere,$field),\Our\ApiConst::oneHour);
                if($result){
                    return $result;
                }
            }
        }
        return false;
    }

    public function getStoreTopClasses($data){
        $storeOnlineGoodsClassDao = \DAO\GoodsClass\StoreOnlineGoodsClassModel::getInstance();
        $storeOnlineGoodsClassDao->checkStoreTopClasses($data);
        $list = \Our\RedisHelper::cachedFunction(\Redis\Db6\StoreOnlineGoodsClassRedisModel::getInstance(),array(&$storeOnlineGoodsClassDao, 'getList'),array(array('store_id'=>$data['storeId']),'distinct(gc_id_1) as gcId'),\Our\ApiConst::oneHour,array($data['storeId']));
        $returnClasses = array();
        if($list){
            $goodsClassDao = \DAO\GoodsClassModel::getInstance();
            $parentClasses = $goodsClassDao->getParentClasses();
            $returnClasses = array_intersect_key($parentClasses,array_flip(array_column($list,'gcId')));
            $returnClasses = array_values($returnClasses);
        }
        return array('classes'=>$returnClasses);
    }

    public function getStoreChildrenClasses($data){
        $storeOnlineGoodsClassDao = \DAO\GoodsClass\StoreOnlineGoodsClassModel::getInstance();
        $storeOnlineGoodsClassDao->checkStoreChildrenClasses($data);

        $gcIdsArray = $storeOnlineGoodsClassDao-> getStoreOnlineGoodsClassesByGcIdFromCache($data['gcId'],$data['storeId']);
        if($gcIdsArray){
            $return = array();
            $secondGcIds = $gcIdsArray['secondGcIds'];
            $treeGcIds = $gcIdsArray['treeGcIds'];
            $platThirdGcIds = $gcIdsArray['platThirdGcIds'];
            $storeThirdGcIds = $gcIdsArray['storeThirdGcIds'];

            $goodsClassDao = \DAO\GoodsClassModel::getInstance();
            $newSecondGcList = array();
            if($secondGcIds){
                $whereSql = \Our\Common::format(' gc_id in ({0})',implode(',',$secondGcIds));
                $secondGcList=$goodsClassDao->getList('gc_id as gcId,gc_name as gcName',$whereSql);
                foreach($secondGcList as $secTemp){
                    $newSecondGcList[$secTemp['gcId']] = $secTemp;
                }
            }
            $newPlatThirdGcList = array();
            if($platThirdGcIds){
                $whereSql = \Our\Common::format(' gc_id in ({0})',implode(',',$platThirdGcIds));
                $platThirdGcList=$goodsClassDao->getList('gc_id as gcId,gc_name as gcName',$whereSql);
                foreach($platThirdGcList as $platThirdTemp){
                    $platThirdTemp['gcImage'] = \Our\Common::getStaticFile(\Our\ImageConst::categoryPicPrefix.$platThirdTemp['gcId'].\Our\NameConst::jpgSuffix,\Our\ImageConst::defaultPath);
                    $newPlatThirdGcList[$platThirdTemp['gcId']] = $platThirdTemp;
                }
            }
            $storeThirdGcList = array();
            if($storeThirdGcIds){
                $storeThirdGcList = \DAO\GoodsClass\GoodsClassThirdModel::getInstance()->getListByIdsFromCache($storeThirdGcIds);

            }
            if($secondGcIds&&$newSecondGcList){
                $classes = array();
                foreach($secondGcIds as $secondGcId){
                    $returnTemp=$newSecondGcList[$secondGcId];
                    $childrenClasses = array();
                    if(isset($treeGcIds[$secondGcId][\Our\ApiConst::zero])&&$newPlatThirdGcList){
                        foreach($treeGcIds[$secondGcId][\Our\ApiConst::zero] as $tempPaltThirdGcId){
                            $tempPlatClass = $newPlatThirdGcList[$tempPaltThirdGcId];
                            $tempPlatClass['storeFlag'] = \Our\ApiConst::zero;
                            $childrenClasses[] = $tempPlatClass;
                        }
                    }
                    if(isset($treeGcIds[$secondGcId][\Our\ApiConst::one])&&$storeThirdGcList){
                        foreach($treeGcIds[$secondGcId][\Our\ApiConst::one] as $tempStoreThirdGcId){
                            $tempStoreClass = $storeThirdGcList[$tempStoreThirdGcId] ;
                            $tempStoreClass['storeFlag'] = \Our\ApiConst::one;
                            $childrenClasses[] = $tempStoreClass;
                        }
                    }
                    $returnTemp['childClasses'] = $childrenClasses;
                    $classes[] = $returnTemp;
                }
                $return['classes']= $classes;
                $return['gcAdvs'] = $this->getStoreTopCalssAdvsFromCache($data);
                return $return;
            }
        }
        \Error\ErrorModel::throwException(\Error\CodeConfigModel::wrongGcIdForStoreIdChildrenClass);

    }

    public function getStoreTopCalssAdvsFromCache($data){
        $adv = \Our\RedisHelper::cachedFunction(\Redis\Db9\GoodsClassImageRedisModel::getInstance(),array(&$this, 'getStoreTopClassAdvs'),array($data['storeId'],$data['gcId']),\Our\ApiConst::oneDaySecond,array($data['gcId'].'_'.$data['storeId']));
        return $adv;
    }


    /**
     * 删除店铺分类顶部缓存
     * @param $gcId
     * @param $storeId
     */
    public function deleteStoreTopClassAdvsFromCache($storeId,$gcId){
        $goodsClassImageDao = \DAO\Adv\GoodsClassImageModel::getInstance();
        if($gcId&&$storeId){
            \Our\RedisHelper::delCachedFunction(\Redis\Db9\GoodsClassImageRedisModel::getInstance(),array(&$this, 'getStoreTopClassAdvs'),array(),array($gcId.'_'.$storeId));
            \Our\RedisHelper::delCachedFunction(\Redis\Db9\GoodsClassImageRedisModel::getInstance(),array(&$goodsClassImageDao, 'find'),array(),array($gcId.'_'.$storeId));
        }else if($gcId){
            \Our\RedisHelper::delCachedFunction(\Redis\Db9\GoodsClassImageRedisModel::getInstance(),array(&$this, 'getStoreTopClassAdvs'),array(),array($gcId));
            \Our\RedisHelper::delCachedFunction(\Redis\Db9\GoodsClassImageRedisModel::getInstance(),array(&$goodsClassImageDao, 'find'),array(),array($gcId));
        }
        return true;
    }

    public function getStoreTopClassAdvs($storeId,$gcId){
        $goodsClassImage = \DAO\Adv\GoodsClassImageModel::getInstance()->findByStoreIdAndGcId($storeId,$gcId);
        $adv['isSwiper'] = \Our\ApiConst::zero;
        $adv['intervalTime'] = \Our\ApiConst::zero;
        if(isset($goodsClassImage['gc_images_name'])&&$goodsClassImage['gc_images_name']){
            $classImage=unserialize($goodsClassImage['gc_images_name']);
            if(count($classImage)>1){
                $adv['isSwiper'] = \Our\ApiConst::one;
                $adv['intervalTime'] = \Our\ApiConst::defaultIntervalTime;
            }
            foreach ($classImage as &$val){
                $val['image']= \Our\Common::getStaticFile($val['image'],\Our\ImageConst::storeClassAdvImagePrefix);
            }
            $adv['advImages'] = $classImage;
        }else{
            $advImage['href'] = \Our\NameConst::emptyString;
            $advImage['image'] = \Our\ImageUtil::getTopClassAdvImageUrl($gcId);
            $adv['advImages'][] =$advImage;
        }
        return $adv;

    }


    private static $_instance = null;

    /**
     * 单例模式获取类实例
     *
     */
    public static function getInstance() {
        if (!(self::$_instance instanceof self)) {
            self::$_instance = new self();
        }

        return self::$_instance;
    }
}