<?php
/**
 * The control file of block module of ZDOO.
 *
 * @copyright   Copyright 2009-2018 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
 * @license     ZPL (http://zpl.pub/page/zplv12.html)
 * @author      Tingting Dai <daitingting@xirangit.com>
 * @package     block
 * @version     $Id$
 * @link        http://www.zdoo.com
 */
class block extends control
{
    /**
     * Block Index Page.
     *
     * @access public
     * @return void
     */
    public function index()
    {
        $lang = $this->get->lang;
        $this->app->setClientLang($lang);
        $this->app->loadLang('common', 'cash');
        $this->app->loadLang('block');

        $mode = strtolower($this->get->mode);
        if($mode == 'getblocklist')
        {
            echo $this->block->getAvailableBlocks();
        }
        elseif($mode == 'getblockform')
        {
            $code = strtolower($this->get->blockid);
            $func = 'get' . ucfirst($code) . 'Params';
            echo $this->block->$func();
        }
        elseif($mode == 'getblockdata')
        {
            $code = strtolower($this->get->blockid);
            $func = 'print' . ucfirst($code) . 'Block';
            $this->$func();
        }
    }

    /**
     * Block Admin Page.
     *
     * @param  int    $id
     * @param  string $type == block field in mysql
     * @access public
     * @return void
     */
    public function admin($id = 0, $type = '')
    {
        $this->app->loadLang('block', 'sys');

        if($_POST)
        {
            $this->block->save($id, 'system', 'cash');
            if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::geterror()));
            return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->server->http_referer));
        }

        $block = $this->block->getByID($id, 'cash');
        $type  = $type ? $type : ($block ? $block->block : '');

        $blocks = json_decode($this->block->getAvailableBlocks(), true);
        $this->view->blocks  = array_merge(array(''), $blocks);

        $title = $id == 0 ? $this->lang->block->createBlock : $this->lang->block->editBlock;

        $this->view->title      = $title;
        $this->view->params     = $type ? json_decode($this->block->{'get' . ucfirst($type) . 'Params'}(), true) : array();
        $this->view->type       = $type;
        $this->view->block      = $block;
        $this->view->id         = $id;
        $this->view->modalWidth = 384;
        $this->display();
    }

    /**
     * Sort block.
     *
     * @param  string    $orders
     * @access public
     * @return void
     */
    public function sort($orders)
    {
        $this->locate($this->createLink('sys.block', 'sort', "orders=$orders&app=cash"));
    }

    /**
     * Resize block
     *
     * @param  int    $id
     * @param  string $type
     * @param  string $data
     * @access public
     * @return void
     */
    public function resize($id, $type, $data)
    {
        $this->locate($this->createLink('sys.block', 'resize', "id=$id&type=$type&data=$data"));
    }

    /**
     * Delete block.
     *
     * @param  int    $id
     * @access public
     * @return void
     */
    public function delete($id)
    {
        $this->locate($this->createLink('sys.block', 'delete', "id=$id"));
    }

    /**
     * Print depositor block.
     *
     * @access public
     * @return void
     */
    public function printDepositorBlock()
    {
        $this->app->loadLang('depositor', 'cash');

        $this->processParams();

        $this->view->depositors   = $this->dao->select('*')->from(TABLE_DEPOSITOR)->where('status')->eq('normal')->fetchAll('id');
        $this->view->balances     = $this->loadModel('balance', 'cash')->getLatest();
        $this->view->currencySign = $this->loadModel('common')->getCurrencySign();
        $this->display();
    }

    /**
     * Print trade block.
     *
     * @access public
     * @return void
     */
    public function printTradeBlock()
    {
        $this->app->loadLang('trade', 'cash');

        $this->processParams();

        /* Do not get trades which user has no privilege to browse their categories. */
        $denyCategories  = array();
        $outCategories   = $this->dao->select('*')->from(TABLE_CATEGORY)->where('type')->eq('out')->fetchAll('id');
        $allowCategories = $this->loadModel('tree')->process($outCategories);
        $denyCategories  = array_diff(array_keys($outCategories), array_keys($allowCategories));

        $rights          = $this->app->user->rights;
        $expensePriv     = (isset($rights['tradebrowse']['out']) or $this->app->user->admin == 'super') ? true : false;
        $laborPirv       = isset($rights['trade']['laborcost']);  // Can see the expensive of labor cost.
        $laborCategories = isset($this->config->laborCategories) ? $this->config->laborCategories : '';

        $this->params->type = !empty($this->params->type) ? $this->params->type : 'all';

        $orderBy = $this->params->orderBy;
        if(strpos($orderBy, 'id') === false)
        {
            $sort = substr($orderBy, strpos($orderBy, '_'));
            $orderBy .= ',id' . $sort;
        }

        $this->view->trades = $this->dao->select('*')->from(TABLE_TRADE)
            ->where('parent')->eq('0')
            ->beginIF($this->params->type != 'all')->andWhere('type')->eq($this->params->type)->fi()
            ->beginIF(!empty($denyCategories))->andWhere('category')->notin($denyCategories)
            ->beginIF(!$expensePriv)->andWhere('type')->ne('out')->fi()
            ->beginIF(!$laborPirv && $laborCategories)->andWhere('category')->notin($laborCategories)->fi()
            ->orderBy($orderBy)
            ->limit($this->params->num)
            ->fetchAll('id');

        $this->view->currencySign  = $this->loadModel('common')->getCurrencySign();
        $this->view->depositorList = $this->loadModel('depositor', 'cash')->getPairs();
        $this->view->customerList  = $this->loadModel('customer')->getPairs();
        $this->view->productList   = $this->loadModel('product')->getPairs();
        $this->view->longBlock     = $this->get->longblock;
        $this->view->type          = $this->params->type;
        $this->view->categories    = $this->lang->trade->categoryList + $this->loadModel('tree')->getPairs('out') + $this->tree->getPairs('in');
        $this->display();
    }

    /**
     * Print base facts block.
     *
     * @access public
     * @return void
     */
    public function printBasefactsBlock()
    {
        $this->processParams();

        $trades = $this->loadModel('trade')->getByYear(date('Y'));
        $annualChartDatas = array();
        foreach($trades as $month => $monthTrades)
        {
            $annualChartDatas[$month]['in']  = 0;
            $annualChartDatas[$month]['out'] = 0;
            foreach($monthTrades as $trade)
            {
                if($trade->type == 'in')  $annualChartDatas[$month]['in']  += $trade->money * $trade->exchangeRate;
                if($trade->type == 'out') $annualChartDatas[$month]['out'] += $trade->money * $trade->exchangeRate;
            }
            $annualChartDatas[$month]['profit'] = $annualChartDatas[$month]['in'] - $annualChartDatas[$month]['out'];
        }

        krsort($annualChartDatas, SORT_STRING);
        foreach($annualChartDatas as $month => $annualChartData)
        {
            foreach($annualChartData as $type => $data)
            {
                $annualChartDatas[$month][$type] = abs($data) >= 10000 ? round($data / 10000, 2) . $this->lang->trade->report->unitList[10000] : round($data, 2);
            }
        }

        $this->view->annualChartDatas = $annualChartDatas;
        $this->view->currencySign     = $this->loadModel('common')->getCurrencySign();
        $this->display();
    }

    /**
     * Print provider block.
     *
     * @access public
     * @return void
     */
    public function printProviderBlock()
    {
        $this->app->loadLang('provider', 'cash');

        $this->session->set('providerList', $this->createLink('cash.dashboard', 'index'));
        if($this->get->app == 'sys')
        {
            $dashboardLink = $this->createLink('my');
            $this->session->set('providerList', "javascript:$.openEntry(\"dashboard\", \"{$dashboardLink}\")");
        }

        $this->processParams();

        $this->view->providers = $this->dao->select('*')->from(TABLE_CUSTOMER)
            ->where('deleted')->eq('0')
            ->andWhere('relation')->eq('provider')
            ->orderBy($this->params->orderBy)
            ->limit($this->params->num)
            ->fetchAll('id');

        $this->view->areas      = $this->loadModel('tree')->getOptionMenu('area');
        $this->view->industries = $this->tree->getOptionMenu('industry');
        $this->display();
    }

    /**
     * Print report block.
     *
     * @access public
     * @return void
     */
    public function printReportBlock()
    {
        $this->processParams();

        $currentYear  = date('Y');
        $currentMonth = date('m');

        $datas = $this->loadModel('trade', 'cash')->getChartData($this->params->type, $currentYear, $currentMonth, $this->params->groupBy, $this->params->currency);
        $datas = $this->loadModel('report')->computePercent($datas);

        $this->view->datas        = $datas;
        $this->view->type         = $this->params->type;
        $this->view->groupBy      = $this->params->groupBy;
        $this->view->currentYear  = $currentYear;
        $this->view->currentMonth = $currentMonth;
        $this->display();
    }

    /**
     * Print invest and loan block.
     *
     * @access public
     * @return void
     */
    public function printFundsBlock()
    {
        $this->app->loadLang('trade', 'cash');
        $this->processParams();

        $trades = $this->dao->select('type, money, exchangeRate')->from(TABLE_TRADE)
            ->where('parent')->eq('0')
            ->andWhere('type', true)->eq('invest')
			->orWhere('type')->eq('loan')
			->orWhere('type')->eq('redeem')
			->orWhere('type')->eq('repay')
			->markRight(1)
            ->fetchAll();

        $totalMoney = array();
        $totalMoney['invest'] = 0;
        $totalMoney['redeem'] = 0;
        $totalMoney['loan']   = 0;
        $totalMoney['repay']  = 0;

        foreach($trades as $trade) $totalMoney[$trade->type] += $trade->money * $trade->exchangeRate;

        if($totalMoney['redeem'] > $totalMoney['invest']) $totalMoney['redeem'] = $totalMoney['invest'];
        if($totalMoney['repay']  > $totalMoney['loan'])   $totalMoney['repay']  = $totalMoney['loan'];

        $totalMoney['unredeem']       = $totalMoney['invest'] - $totalMoney['redeem'];
        $totalMoney['unrepay']        = $totalMoney['loan'] - $totalMoney['repay'];
        $totalMoney['investprogress'] = $totalMoney['invest'] ? round($totalMoney['redeem'] / $totalMoney['invest'] * 100, 2) . '%' : '0%';
        $totalMoney['loanprogress']   = $totalMoney['loan'] ? round($totalMoney['repay'] / $totalMoney['loan'] * 100, 2) . '%' : '0%';

        $this->view->data = $totalMoney;
        $this->display();
    }

    /**
     * Print chart block.
     *
     * @access public
     * @return void
     */
    public function printChartBlock($year = '', $type = '', $currency = '', $unit = 10000)
    {
        $this->app->loadLang('trade', 'cash');
        $this->processParams();

        if(!$year)     $year     = date('Y');
        if(!$type)     $type     = $this->params->type;
        if(!$currency) $currency = $this->params->currency;
        $trades = $this->dao->select('`type`, `date`, `money`')->from(TABLE_TRADE)
            ->where('parent')->eq('0')
            ->andWhere('currency')->eq($currency)
            ->andWhere('date')->like("{$year}%")
            ->andWhere('type')->in('in,out')
            ->fetchAll();

        $getDataFunc = 'get' . ucfirst($type) . 'ChartData';
        $param       = $type != 'monthCash' ? $trades : array('currency' => $currency, 'unit' => $unit);
        if(in_array($type, array('monthTrade', 'monthProfit'))) $param = array('trades' => $trades, 'unit' => $unit);
        $data        = $this->$getDataFunc($param);

        $this->view->chartTitle = ($type != 'monthCash' ? $year . $this->lang->year : '') .  $this->lang->block->typeList->chart[$type] . " (" . zget($this->lang->currencyList, $currency) . $this->lang->colon . $this->lang->trade->report->unitList[10000] . ")";
		$this->view->type       = $type;
        $this->view->longBlock  = $this->get->longblock;
        $this->view->data       = $data;
        $this->display();
    }

    /**
     * Get yearProfit chart data.
     * 
     * @param  array    $trades 
     * @access public
     * @return object
     */
    public function getYearProfitChartData($trades)
    {
        $total = array();
        $total['in'] = $total['out'] = 0;
        foreach($trades as $trade) $total[$trade->type] += $trade->money;
        $total['profit'] = $total['in'] - $total['out'];

        $dataset = new stdClass();
        $dataset->data            = array(round($total['in'] / 10000, 2), round($total['out'] / 10000, 2), round($total['profit'] / 10000, 2));
        $dataset->backgroundColor = array_values($this->config->block->chartOptions['color']);
        $dataset->barPercentage   = '0.5';

        $data = new stdclass();
        $data->labels   = $this->lang->block->yearProfitAxis; 
        $data->datasets = array($dataset);

        return $data;
    }

    /**
     * Get monthTrade chart data.
     * 
     * @param  array    $params 
     * @access public
     * @return object
     */
    public function getMonthTradeChartData($params)
    {
        $trades = isset($params['trades']) ? $params['trades'] : array();
        $unit   = isset($params['unit'])   ? $params['unit'] : 10000;
        /* Statistics by granularity.*/
        $statistics = array();
        foreach($trades as $trade)
        {
            $month = substr($trade->date, 5, 2);
            if(!isset($statistics[$month][$trade->type])) $statistics[$month][$trade->type] = 0;
            $statistics[$month][$trade->type] += $trade->money;
        }

        /* Complete profit of all months.*/
        $datasetsData = array();
        foreach($this->lang->block->months as $month => $monthName)
        {
            $datasetsData['in'][]  = isset($statistics[$month]['in']) ? round($statistics[$month]['in'] / $unit, 2) : 0;
            $datasetsData['out'][] = isset($statistics[$month]['out']) ? round($statistics[$month]['out'] / $unit, 2) : 0;
        }

        /* Generate the format required by chartjs. */
        $datasets = array(); 
        foreach($this->config->block->monthTradeCharts as $tradeType => $chartTypes)
        {
            foreach($chartTypes as $chartType)
            {
                $chart = new stdclass();
                $chart->label           = $this->lang->block->typeList->trade[$tradeType];
                $chart->data            = $datasetsData[$tradeType];
                $chart->backgroundColor = $this->config->block->chartOptions['color'][$tradeType];
                $chart->showData        = true; 
                $chart->order           = 2;

                if($chartType == 'line')
                {
                    $chart->type            = 'line';
                    $chart->tension         = 0;
                    $chart->borderColor     = $this->config->block->chartOptions['color'][$tradeType];  
                    $chart->backgroundColor = 'rgba(0, 0, 0, 0)';
                    $chart->showData        = false; 
                    $chart->order           = 1;
                }

                $datasets[] = $chart;
            }
        }

        $data = new stdclass();
        $data->labels   = array_values($this->lang->block->months); 
        $data->datasets = $datasets;

        return $data;
    }

    /**
     * Get monthProfit chart data.
     * 
     * @param  array    $params 
     * @access public
     * @return object
     */
    public function getMonthProfitChartData($params)
    {
        $trades = isset($params['trades']) ? $params['trades'] : array();
        $unit   = isset($params['unit'])   ? $params['unit']   : 10000;
        /* Statistics by granularity.*/
        $statistics = array();
        foreach($trades as $trade)
        {
            $month = substr($trade->date, 5, 2);

            if(!isset($statistics[$month][$trade->type])) $statistics[$month][$trade->type] = 0;
            $statistics[$month][$trade->type] += $trade->money;
        }

        /* Statistics monthly profit. */
        foreach($statistics as $month => $statistic) $statistics[$month]['profit'] = zget($statistic, 'in', 0) - zget($statistic, 'out', 0);

        /* Complete profit of all months.*/
        $datasetsData = array();
        foreach($this->lang->block->months as $month => $monthName) $datasetsData[] = isset($statistics[$month]['profit']) ? round($statistics[$month]['profit'] / $unit, 2) : 0;

        /* Generate the format required by chartjs. */
        $datasets = array(); 
        foreach($this->config->block->monthProfitCharts as $chartType)
        {
            $chart = new stdClass();
            $chart->data            = $datasetsData; 
            $chart->backgroundColor = $this->config->block->chartOptions['color']['profit'];
            $chart->order           = 2;
            $chart->showData        = true;

            if($chartType == 'line')
            {
                $chart->type            = $chartType; 
                $chart->borderColor     = $this->config->block->chartOptions['color']['profit'];  
                $chart->backgroundColor = 'rgba(0, 0, 0, 0)';
                $chart->tension         = 0;
                $chart->order           = 1;
                $chart->showData        = false;
            }

            $datasets[] = $chart;
        }

        $data = new stdclass();
        $data->labels   = array_values($this->lang->block->months); 
        $data->datasets = $datasets;

        return $data;
    }

    /**
     * Get monthCash chart data.
     *
     * @param  string $currency
     * @access public
     * @return object
     */
    public function getMonthCashChartData($params)
    {
        $currency = isset($params['currency']) ? $params['currency'] : '';
        $unit     = isset($params['unit'])     ? $params['unit']     : 10000;
        if(!$currency) $currency = $this->params->currency;

        $beginDate = date('Y-m-01', strtotime(' -11 month'));
        $balances = $this->dao->select('t2.depositor, t2.money, t2.date, DATE_FORMAT(t2.date, "%Y%m") AS month')->from(TABLE_DEPOSITOR)->alias('t1')
            ->leftJoin(TABLE_BALANCE)->alias('t2')->on('t1.id = t2.depositor')
            ->where('t1.status')->eq('normal')
            ->andWhere('t2.`date`')->ge($beginDate)
            ->andWhere('t2.currency')->eq($currency)
            ->orderBy('date_desc')
            ->fetchAll();

        $monthDepositors = array();
        foreach($balances as $balance)
        {
            if(!isset($monthDepositors[$balance->month])) $monthDepositors[$balance->month] = array();
            if(!isset($monthDepositors[$balance->month][$balance->depositor]) or $monthDepositors[$balance->month][$balance->depositor]->date < $balance->date) 
            {
                $monthDepositors[$balance->month][$balance->depositor] = $balance;
            }
        }

        $statistics = array();
        foreach($monthDepositors as $month => $depositors)
        {
            $statistics[$month] = 0;
            foreach($depositors as $depositor) $statistics[$month] += $depositor->money;
        }

        $labels = array();
        if($beginDate == date('Y-01-01'))
        {
            $labels = array_keys($this->lang->block->months);
        }
        else
        { 
            for($i = 0; $i < 12; $i ++) $labels[] = date('Y/m', strtotime($beginDate . "+{$i} month"));
        }

        $datasetsData = array();
        foreach($labels as $label)
        {
            $month = $beginDate == date('Y-01-01') ? date('Y') . $label : str_replace('/', '', $label);
            $datasetsData[] = isset($statistics[$month]) ? round($statistics[$month] / $unit, 2) : 0;
        }

        $dataset  = new stdClass();
        $dataset->data            = $datasetsData;
        $dataset->backgroundColor = $this->config->block->chartOptions['color']['in'];
            
        $data = new stdclass();
        $data->labels   = $labels;
        $data->datasets = array($dataset);
        return $data;
    }

    /**
     * Process params.
     *
     * @access public
     * @return void
     */
    public function processParams()
    {
        $params = $this->get->param;
        $this->params = json_decode(base64_decode($params));

        $this->view->sso  = base64_decode($this->get->sso);
        $this->view->code = strtolower($this->get->blockid);
    }
}
