<?php
/**
 * Created by PhpStorm.
 * User: stanley-king
 * Date: 16/4/17
 * Time: 下午11:34
 */

namespace bonus;

require_once(BASE_ROOT_PATH . '/helper/model_helper.php');
require_once(BASE_ROOT_PATH . '/helper/algorithm.php');
require_once(BASE_ROOT_PATH . '/helper/util_helper.php');


use session_helper;
use member_info;
use algorithm;
use Log;
use Exception;
use trans_wapper;
use util;

class manager
{
    //红包抢到不绑定手机的过期时间
    const grab_period_timeout = 10 * 60;

    //红包的四种状态
    const bonus_state_ungrab = 0; //未抢
    const bonus_state_grabed = 1; //已抢到
    const bonus_state_binded = 2; //已绑定手机
    const bonus_state_topuped= 3; //已经充值

    public function __construct() {

    }

    const type_prefix = 'bonus_type';

    private function avatars($user_ids)
    {
        $result = [];

        $mod_member = Model('member');
        $items = $mod_member->getMemberList(array('member_id' => array('in',$user_ids)));
        foreach ($items as $item) {
            $member = new member_info($item);
            $uid = $member->member_id();
            $avatar = $member->avatar();
            $discount = $item['discount_self_amount'];
            $result[$uid]['avatar'] = $avatar;
            $result[$uid]['discount'] = $discount;
        }

        return $result;
    }

    public function get_typeinfo($type_sn)
    {
        $bonus_info = rcache($type_sn, self::type_prefix, '*');
        if (empty($bonus_info))
        {
            $type = type::create_by_sn($type_sn,true);
            $user_bonus = Model('user_bonus');
            $bonus_ex= $user_bonus->getTypeBinded(array('type_id' => $type->getType_id()));
            $type_info = $type->get_param();

            if($type->binded_over())
            {
                $lasted_time = Model('user_bonus')->lasted_binded_time(array('type_id' => $type->getType_id()));
                if($lasted_time > 0) {
                    $period = $lasted_time - $type->get_start_time();
                    $type_info['binded_period'] = $period == 0 ? 1 : $period;
                }
                $type_info['binded_over'] = 1;
                $type_info['grab_lastime'] = 0;
            }
            else
            {
                $type_info['binded_period'] = 0;
                $type_info['binded_over'] = 0;
                if($type->grabed_over()) {
                    $lasted_time = Model('user_bonus')->lasted_grabed_time(array('type_id' => $type->getType_id(),'bonus_status' => 1));
                    $type_info['grab_lastime'] = $lasted_time;
                } else {
                    $type_info['grab_lastime'] = 0;
                }
            }

            $user_ids = [];
            $user_ids[] = $type->sender_id();
            foreach ($bonus_ex as $bonus) {
                $user_ids[] = intval($bonus['user_id']);
            }
            $user_avatars = $this->avatars($user_ids);

            $type_sn = $type->getType_sn();
            $url = BASE_SITE_URL . "/mobile/index.php?act=bonusex&op=open&client_type=wap&type_sn={$type_sn}";
            $ret['url'] = $url;

            $bonus_info = array('type_info' => $type_info,'binded_info' => $bonus_ex,'avatars' => $user_avatars);
            wcache($type_sn,array('infos' => serialize($bonus_info)),self::type_prefix);
        }
        else {
            $bonus_info = unserialize($bonus_info['infos']);
        }
        return $bonus_info;
    }

    public function get_mine_by_typesn($type_sn)
    {
        $bonus = $this->read_session($type_sn);
        if(empty($bonus))
        {
            $mod_bonus = Model('user_bonus');

            $session_id = $_SESSION['MPHPSESSID'];
            if(session_helper::isVerfiyMobile()) {
                $mobile = session_helper::cur_mobile();
                $sql = "select * from lrlz_user_bonus where type_sn = '{$type_sn}' and (session_id = '{$session_id}' or user_mobile = '{$mobile}')";
            } else {
                $sql = "select * from lrlz_user_bonus where type_sn = '{$type_sn}' and session_id = '{$session_id}'";
            }
            $bonusex = $mod_bonus->get_by_sql($sql);

            if(empty($bonusex)) {
                return false;
            }
            if(count($bonusex) > 1)
            {
                foreach($bonusex as $val)
                {
                    if($val['user_mobile'] == $_SESSION['member_mobile']) {
                        $this->write_session($val);
                        return $val;
                    }
                }
            }
            else {
                $this->write_session($bonusex[0]);
                return $bonusex[0];
            }
        }

        return $bonus;
    }

    public function get_mine_by_bonussn($bonus_sn)
    {
        $bonus = $this->read_session('',$bonus_sn);
        if(empty($bonus))
        {
            $mod_bonus = Model('user_bonus');
            $session_id = $_SESSION['MPHPSESSID'];
            if(session_helper::isVerfiyMobile()) {
                $mobile = session_helper::cur_mobile();
                $sql = "select * from lrlz_user_bonus where bonus_sn = '{$bonus_sn}' and (session_id = '{$session_id}' or user_mobile = '{$mobile}')";
            } else {
                $sql = "select * from lrlz_user_bonus where bonus_sn = '{$bonus_sn}' and session_id = '{$session_id}'";
            }
            $bonusex = $mod_bonus->get_by_sql($sql);
            if(empty($bonusex)) {
                return false;
            }

            if(count($bonusex) > 1)
            {
                foreach($bonusex as $val)
                {
                    if($val['user_mobile'] == $_SESSION['member_mobile']) {
                        $this->write_session($val);
                        return $val;
                    }
                }
            }
            else {
                $this->write_session($bonusex[0]);
                return $bonusex[0];
            }
        }

        return $bonus;
    }


    public function grab_bonus($type_sn)
    {
        $bonus = $this->read_session($type_sn);
        if($bonus === false)
        {
            $param = array( 'type_sn' => $type_sn,
                'session_id' => $_SESSION['MPHPSESSID'],
                'time_out' => self::grab_period_timeout,
                'member_mobile' => $_SESSION['member_mobile']);

            $bonus_obj = factory::grab_bonus($param);
            if($bonus_obj == false) {
                return false;
            }
            else
            {
                $this->write_session($bonus_obj->get_param());
                dcache($bonus_obj->type_sn(),self::type_prefix);
            }
            $bonus = $bonus_obj->get_param();
        }

        return $bonus;
    }

    public function topup($type,$mod_user_bonus,&$bonus)
    {
        $usable_days  = $type->usable_days();
        $expried_secs = $usable_days * 24 * 3600;
        $usable_time = time() + $expried_secs;
        $usable_time = util::last_day_secs($usable_time);

        $datas = array('bonus_status' => 3,
            'user_id' => $_SESSION['member_id'],
            'user_name' => session_helper::nickname(),
            'usable_time' => $usable_time);

        $ret = $mod_user_bonus->where(array('bonus_id' => $bonus['bonus_id']))->update($datas);
        $affect_rows = $mod_user_bonus->affected_rows();
        if($ret == true && $affect_rows == 1) {
            array_merge($bonus,$datas);
            $this->write_session($bonus);
            return true;
        }
        else {
            return false;
        }
    }

    public function send($type_sn,$ids)
    {
        $member_ids = [];
        foreach ($ids as $id) {
            $member_ids[] = intval($id);
        }
        sort($member_ids);

        $mod_bonus = Model('user_bonus');

        $items = $mod_bonus->getBonusList(array('user_id' => array('in',$member_ids),'type_sn' => $type_sn),'*','',0,0,false,'',true);
        $ret = [];
        foreach ($items as $item)
        {
            $user_id = intval($item['user_id']);
            if(algorithm::binary_search($user_id,$member_ids) != false)
            {
                $pos = algorithm::lower_bonud($member_ids,$user_id);
                algorithm::array_erase($member_ids,$pos);
                $ret[] = $item;
            }
        }

        if(!empty($member_ids))
        {
            $count = count($member_ids);
            $items = $mod_bonus->getBonusList(array('bonus_status' => 0,'type_sn' => $type_sn),'*','',0,0,count($member_ids),'',true);
            if($count != count($items)) {
                return false;
            }

            $index = 0;
            $bonus_values = 0.00;
            foreach ($items as &$bonus)
            {
                try
                {
                    $user_id = $member_ids[$index];
                    $minfo = new member_info($user_id);
                    $bonus['user_id'] = $user_id;
                    $bonus['user_mobile'] = $minfo->mobile();
                    $bonus['user_name'] = $minfo->nickname();
                    $bonus['grab_time'] = time();
                    $bonus['get_time'] = time();
                    $bonus['bonus_status'] = 2;

                    $ret[] = $bonus;
                    $bonus_values += $bonus['bonus_value'];
                } catch (Exception $ex) {
                    Log::record($ex->getMessage(),Log::ERR);
                }
                ++$index;
            }

            $mod_bonus->replaceAll($items);
            Model('bonus_type')->edit(array('type_sn' => $type_sn),
                array('binded_num' => array('exp', "binded_num+{$count}"),
                      'grabed_num' => array('exp', "grabed_num+{$count}"),
                      'remain_amount' => array('exp', "remain_amount-" . "{$bonus_values}")));
            dcache($type_sn,self::type_prefix);

            return $ret;
        } else {
            return false;
        }
    }

    public function send_mobile($type_sn, $mobiles,$status)
    {
        sort($mobiles);
        $mod_bonus = Model('user_bonus');

        $items = $mod_bonus->getBonusList(array('user_mobile' => array('in',$mobiles),'type_sn' => $type_sn),'*','',0,0,false,'',true);
        $ret = [];
        foreach ($items as $item)
        {
            $user_mobile = $item['user_mobile'];
            if(algorithm::binary_search($user_mobile,$mobiles) != false)
            {
                $pos = algorithm::lower_bonud($mobiles,$user_mobile);
                algorithm::array_erase($mobiles,$pos);
                $ret[] = $item;
            }
        }

        if(!empty($mobiles))
        {
            $count = count($mobiles);
            $items = $mod_bonus->getBonusList(array('bonus_status' => 0,'type_sn' => $type_sn),'*','',0,0,count($mobiles),'',true);
            if($count != count($items)) {
                return false;
            }

            $mod_member = Model('member');

            $index = 0;
            $bonus_values = 0.00;

            $bind_num = 0;
            foreach ($items as &$bonus)
            {
                $user_mobile = $mobiles[$index];
                $infos = $mod_member->getMemberInfo(['member_mobile' => $user_mobile]);
                if(!empty($infos)) {
                    $minfo = new member_info($infos);
                    $bonus['user_id'] = $minfo->member_id();
                    $bonus['user_mobile'] = $minfo->mobile();
                    $bonus['user_name'] = $minfo->nickname();
                    $bonus['grab_time'] = time();
                    $bonus['get_time'] = time();
                    $bonus['bonus_status'] = $status;
                    $bind_num++;
                    $bonus_values += $bonus['bonus_value'];
                } else {
                    $bonus['user_mobile'] = $user_mobile;
                    $bonus['grab_time'] = time();
                    $bonus['bonus_status'] = 1;
                }

                ++$index;
                $ret[] = $bonus;
            }

            $mod_bonus->replaceAll($items);
            Model('bonus_type')->edit(array('type_sn' => $type_sn),
                array('binded_num' => array('exp', "binded_num+{$bind_num}"),
                    'grabed_num' => array('exp', "grabed_num+{$count}"),
                    'remain_amount' => array('exp', "remain_amount-" . "{$bonus_values}")));
            dcache($type_sn,self::type_prefix);

            return $ret;
        } else {
            return false;
        }
    }

    public function bind_bonus($bonus_sn,$session_id,$mobile,&$new_bonus_sn)
    {
        $new_bonus_sn = $bonus_sn;
        $bonus_info = self::read_session('',$bonus_sn);
        if(!empty($bonus_info))
        {
            $user_bonus = user_bonus::create_by_param($bonus_info);
            if($user_bonus->isBinded()) {
                return true;
            } else {
                $bonus_id = $user_bonus->bonus_id();
                $type_id = $user_bonus->type_id();
            }
        }

        if(!isset($type_id))
        {
            $user_bonus = user_bonus::create_by_sn($bonus_sn);
            if($user_bonus->isBinded())
            {
                if($user_bonus->user_mobile() == $mobile) {
                    return true;
                } else {
                    return false;
                }
            }

            $bonus_id = $user_bonus->bonus_id();
            $type_id = $user_bonus->type_id();
        }

        $binded_bonus = array();
        $ret = Model('user_bonus')->bind($type_id,$bonus_id,$session_id,$mobile,$binded_bonus);
        Log::record("bind_bonus bind ret={$ret}",Log::DEBUG);
        if($ret == true)
        {
            try
            {
                //bind 一个新红包
                $bonus_val = $user_bonus->bonus_value();
                $trans = new trans_wapper(null,__METHOD__);
                Model('bonus_type')->edit(array('type_id' => $type_id),
                    array('binded_num' => array('exp', 'binded_num+1'),
                        'remain_amount' => array('exp', "remain_amount-" . "{$bonus_val}")));
                $trans->commit();

                $this->clear_session($bonus_sn);
                dcache($user_bonus->type_sn(),self::type_prefix);
            } catch (Exception $ex) {
                $trans->rollback();
                return false;
            }
        }
        else
        {
            if(!empty($binded_bonus)) { //返回已经绑定的红包
                $this->clear_session($bonus_sn);
                $this->write_session($binded_bonus);
                $new_bonus_sn = $binded_bonus['bonus_sn'];
            } else {
                return false;
            }
        }

        return true;
    }

    public function shake($bonus_sn,$strength,$direction)
    {
        $bonus_info = self::read_session('',$bonus_sn);
        if(!empty($bonus_info))
        {
            $user_bonus = user_bonus::create_by_param($bonus_info);
            $bonus_id = $user_bonus->bonus_id();
            $type_id = $user_bonus->type_id();
            $bonus_val = $user_bonus->bonus_value();
            $bonus_status = $user_bonus->bonus_status();
        }

        if(!isset($type_id)) {
            $user_bonus = user_bonus::create_by_sn($bonus_sn);
            $bonus_id = $user_bonus->bonus_id();
            $type_id = $user_bonus->type_id();
            $bonus_val = $user_bonus->bonus_value();
            $bonus_status = $user_bonus->bonus_status();
        }

        if($user_bonus->can_shake() == false) {
            return false;
        }

        $shaker = new \bonus\shaker();
        $ret = $shaker->reassign($type_id,$bonus_id,$bonus_status,$bonus_val,$strength,$direction);
        if($ret == true)
        {
            $bonus = $this->read_session('',$bonus_sn);
            if(!empty($bonus)) {
                $this->clear_session($bonus_sn);
                $bonus['bonus_value'] = $bonus_val;
                $this->write_session($bonus);
            }
            dcache($user_bonus->type_sn(),self::type_prefix);
            
            return true;
        } else {
            return false;
        }
    }

    public function comment($bonus_sn,$content)
    {
        if(empty($bonus_sn)) return false;

        $condition = array('user_mobile' => $_SESSION['member_mobile'],
            'bonus_sn' => $bonus_sn,
            'bonus_status' => array('in',array(2,3)));
        $ret = Model('user_bonus')->edit($condition,array('user_comment' => $content));
        if($ret == true) {
            $user_bonus = user_bonus::create_by_sn($bonus_sn);
            dcache($user_bonus->type_sn(),self::type_prefix);
            return true;
        } else {
            return false;
        }
    }

    //个人抢到的红包，放到个人的Session 里面.
    private function read_session($type_sn,$b_sn = '')
    {
        if(!isset($_SESSION['bonus'])) return false;

        $bonusex = $_SESSION['bonus'];
        foreach($bonusex as $bonus_sn => $val)
        {
            if($bonus_sn == $b_sn) return $val;
            if($val['type_sn'] == $type_sn)
            {
                $status = $val['bonus_status'];
                if ($status == self::bonus_state_binded) {
                    return $val;
                }
                else if ($status == self::bonus_state_grabed)
                {
                    $grab_time = $val['grab_time'];
                    if ($grab_time > time() - self::grab_period_timeout) {
                        return $val;
                    } else {
                        unset ($_SESSION['bonus'][$bonus_sn]);
                        return false; // 需要重新抢
                    }
                }
                else {
                    return $val;
                }
            }
        }

        return false;
    }

    private function write_session($bonus)
    {
        if(!isset($_SESSION['bonus'])) {
            $_SESSION['bonus'] = array();
        }

        $bonus_sn = $bonus['bonus_sn'];
        $_SESSION['bonus'][$bonus_sn] = $bonus;
    }

    private function clear_session($bonus_sn = '')
    {
        if(!empty($bonus_sn))
        {
            if(isset($_SESSION['bonus']) && isset($_SESSION['bonus'][$bonus_sn]))  {
                unset($_SESSION['bonus'][$bonus_sn]);
            }
        }
        else
        {
            if(!isset($_SESSION['bonus'])) {
                unset($_SESSION['bonus']);
            }
        }
    }
}