<?php
/**
 * Created by PhpStorm.
 * User: stanley-king
 * Date: 16/4/10
 * Time: 下午9:42
 */

namespace bonus;

use \Exception;
use \errcode;
use \Log;

abstract class IGenerator
{
    protected $mType;
    public function __construct($type) {
        $this->mType = $type;
    }

    abstract public function make_bonus($rates);

    public function make_type()
    {
        $this->mType->setType_sn(make_bonus_sn());
        $param = $this->mType->get_param();
        $id = Model('bonus_type')->add($param);
        if($id > 0) {
            $this->mType->setType_id($id);
        } else {
            throw new Exception("生成红包类型失败",errcode::ErrBonusMake);
        }
    }
    public function type_sn() {
        return $this->mType->getType_sn();
    }
}
//发给指定人群的红包
class DirectGenerator extends IGenerator
{
    public function __construct($type) {
        parent::__construct($type);
    }

    public function make_bonus($rates)
    {
    }
}

//发个任意人群的红包
class GeneralGenerator extends IGenerator
{
    private $mDatas;
    public function __construct($type) {
        parent::__construct($type);
    }

    public function make_bonus($rates)
    {
        $paramer = $this->mType->get_param();
        $type_id = $this->mType->getType_id();
        $type_sn = $this->mType->getType_sn();

        $this->mDatas = [];

        $min_val = -1;
        $max_val = -1;
        foreach ($rates as $item)
        {
            $amount = $item['amount'];
            $num    = $item['num'];
            $rate   = $item['rate'];

            if($this->mType->isRandomAmount())
            {
                $this->random($type_id,$type_sn,$paramer['min_amount'],$amount,$num,$rate,$min_tmp,$max_tmp);
                if($min_val == -1) {
                    $min_val = $min_tmp;
                }
                else
                {
                    if(intval($min_tmp * 100 + 0.5) < intval($min_val * 100 + 0.5)) {
                        $min_val = $min_tmp;
                    }
                }

                if($max_val == -1) {
                    $max_val = $max_tmp;
                }
                else
                {
                    if(intval($max_tmp * 100 + 0.5) > intval($max_val * 100 + 0.5)) {
                        $max_val = $max_tmp;
                    }
                }
            }
            else
            {
                $fixed_money =  $amount;
                $this->general($type_id,$type_sn,$num,$fixed_money,$rate);
            }
        }

        if(empty($this->mDatas)) {
            return false;
        }

        $bonus = $this->mislead();
        $mod_bonus = Model('user_bonus');
        $ret = $mod_bonus->insertAll($bonus);
        if(!$ret) {
            Log::record("insert user_bonus err: type_id = {$type_id}.");
            return false;
        }

        if($this->mType->isRandomAmount()) {
            Model('bonus_type')->edit(array('type_id' => $type_id),array('min_amount' => $min_val,'max_amount' => $max_val));
        }
        return true;
    }

    private function mislead()
    {
        $ret = $this->mDatas;
        $num = count($ret);
        for($index = 0; $index < $num - 1; $index++) {
            $pos_a = mt_rand(0, $num - 1);
            $pos_b = mt_rand(0, $num - 1);

            $tmp = $ret[$pos_a];
            $ret[$pos_a] = $ret[$pos_b];
            $ret[$pos_b] = $tmp;
        }
        return $ret;
    }

    private function random($type_id,$type_sn,$min_amount,$amount,$num,$rate,&$min_val,&$max_val)
    {
        $allocator = new allocator();
        $moneys = $allocator->separate_money($min_amount,$amount,$num,$min_val,$max_val);

        foreach($moneys as $val)
        {
            $item = array('bonus_sn' => make_bonus_sn(),
                'bonus_value' => $val,
                'remain_amount' => $val,
                'type_id' => $type_id,
                'bonus_status' => 0,
                'bonus_rate' => $rate,
                'type_sn' => $type_sn);

            $this->mDatas[] = $item;
        }
    }

    private function general($type_id,$type_sn,$total_num,$fixed_money,$rate)
    {
        $val =  $fixed_money;
        for($i = 0; $i < $total_num; $i++)
        {
            $item = array( 'bonus_sn' => make_bonus_sn(),
                'bonus_value' => $val,
                'remain_amount' => $val,
                'type_id' => $type_id,
                'bonus_status' => 0,
                'bonus_rate' => $rate,
                'type_sn' => $type_sn);
            $this->mDatas[] = $item;
        }
    }
}


function create_generator($type)
{
    if($type->isDirectType()) {
        return new DirectGenerator($type);
    }
    else if($type->isGeneralType()) {
        return new GeneralGenerator($type);
    }
    else {
        throw new Exception("错误的红包类型",errcode::ErrBonusType);
    }
}
