<?php

namespace Api\PhpServices\Printer\Fei;

/**
 * 飞蛾 打印实现类
 *
 * @author mengweifu
 * @date 2021-7-25 14:00:00
 */

use Api\PhpUtils\Http\HttpUtil;

class FeiPrinter extends \Api\PhpServices\Printer\Printer
{
    /**
     * *必填*：账号名
     */
    private  const  USER = "yonghui.chen@linkingcities.com";
    /**
     * *必填*: 飞鹅云后台注册账号后生成的UKEY 【备注：这不是填打印机的KEY】
     */
    private  const  UKEY = "VjPMkB64QNuIIcgQ";
    /**
     * 飞鹅云打印 api前缀 不需要修改
     */
    private  const  API = "http://api.feieyun.cn/Api/Open/";

    /**
     * 打印订单
     */
    private  const  API_PRINT = "Open_printMsg";
    /**
     * 查询打印订单状态
     */
    private  const  API_ORDER_STATUS = "Open_queryOrderState";
    /**
     * 获取某台打印机状态
     */
    private  const  API_PRINTER_STATUS = "Open_queryPrinterStatus";

    /**
     * 添加打印机
     */
    private  const  API_ADD_PRINTER = "Open_printerAddlist";

    /**
     * 打印(标签)
     */
    private  const API_LABEL_PRINT = "Open_printLabelMsg";

    /**
     * 标签打印常量
     */
    private const LABEL_WIDTH           = 320;
    private const LABEL_HIGH            = 240;
    private const LABEL_FONT            = 12;
    private const LABEL_MARGIN_WIDTH    = 20;
    private const LABEL_MARGIN_HIGH     = 20;
    private const LABEL_PADDING         = 45;
    private const LABEL_FIELD_PADDING   = 30;
    private const LABEL_WORD_FULL_WIDTH = 22.4;
    private const LABEL_WORD_HALF_WIDTH = 11.2;

    /**
     * @param string $apiName api 名字
     * @return array
     */
    private function buildQuery(string $apiName) : array
    {
        $timestamp = time();
        return [
            'user'      => self::USER,
            'stime'     => $timestamp,
            'sig'       => $this->signature(self::USER, self::UKEY, $timestamp),
            'apiname'   => $apiName
        ];
    }

    private function signature(String $user, String $uKey, int $sTime): string
    {
        return sha1($user . $uKey . $sTime);
    }

    /**
     * 内部函数 查询
     * @param string $apiName
     * @param array $param
     * @return array
     */
    private function request(string $apiName,array $param): array
    {
        $param = $this->buildQuery($apiName) + $param;
        return HttpUtil::post(self::API, http_build_query($param));
    }


    private function _printContent(string $printerId,string $content): string
    {
        $res = $this->request(self::API_PRINT, [
            'sn'         => $printerId,
            'content'   => $content,
            'times'     => 1,// 打印联数
        ]);
        if ($res['code'] == 0 && isset($res['response'])) {
            if ($res['response']['ret'] == 0) {
                return $res['response']['data'];
            }
            throw new \Exception($res['response']['msg']);
        }
        throw new \Exception("接口调用异常");
    }

    /**
     * @inheritDoc
     * @throws \Exception
     */
    public function addPrinter(array $param): bool
    {
        $res = $this->request(self::API_ADD_PRINTER, [
            'printerContent'       => "{$param['printer_sn']} # {$param['printer_key']} # {$param['ota_name']}",
        ]);
        if ($res['code'] == 0 && isset($res['response'])) {
            if ($res['response']['ret'] == 0) {
                if (is_array($res['response']['data']['ok']) && count($res['response']['data']['ok']) > 0) {
                    return true;
                }
                if (strpos($res['response']['data']['no'][0], '已被添加过')) {
                    return true;
                }
                throw new \Exception($res['response']['data']['no'][0]);
            }
            throw new \Exception($res['response']['msg']);
        }
        throw new \Exception("接口调用异常");
    }

    /**
     * @inheritDoc
     */
    public function deletePrinter(string $printerId): bool
    {
        // TODO: Implement deletePrinter() method.
    }

    /**
     * @inheritDoc
     * @throws \Exception
     */
    public function getPrinterStatus(string $printerId): string
    {
        $res = $this->request(self::API_PRINTER_STATUS, [
            'sn'    => $printerId,
        ]);
        if ($res['code'] == 0 && isset($res['response'])) {
            if ($res['response']['ret'] == 0) {
                return $res['response']['data'];
            }
            throw new \Exception($res['response']['msg']);
        }
        throw new \Exception("接口调用异常");
    }


    /**
     * @inheritDoc
     * @throws \Exception
     */
    public function printContent(string $printerId, array $content):string
    {
        $formattedContent = "";
        $first = true;
        foreach ($content as $row) {
            $formattedRow = is_array($row) ? implode(' ', $row) : $row;
            if ($first) {
                $formattedContent .= "<CB>$formattedRow</CB><BR>";
            }
            else {
                $formattedContent .= "$formattedRow<BR>";
            }
            $first = false;

            if (strlen($formattedContent) > 4000) {
                $return = self::_printContent($printerId, $formattedContent);
                $formattedContent = "";
            }
        }

        if (!empty($formattedContent))
            $return = self::_printContent($printerId, $formattedContent);

        return $return;
    }

    /**
     * @inheritDoc
     * @throws \Exception
     */
    public function getOrderStatus(string $orderId): bool
    {
        $res = $this->request(self::API_ORDER_STATUS, [
            'orderid'       => $orderId,
        ]);
        if ($res['code'] == 0 && isset($res['response'])) {
            if ($res['response']['ret'] == 0) {
                return (bool) $res['response']['data'];
            }
            throw new \Exception($res['response']['msg']);
        }
        throw new \Exception("接口调用异常");
    }

    /**
     * 测试标签打印机
     * 570203776
     * alter table ota add column  `label_printer_sn` varchar(50)  NOT NULL DEFAULT '' COMMENT '打印机SN' after `printer_key`, add column  `label_printer_key` varchar(50)  NOT NULL DEFAULT '' after `label_printer_sn`;
     * @param string $printerId
     * @param array $content
                $content = [
                    '维多利亚',
                    '西红柿教育-维多利亚D1015',
                    'B:干豆角红烧肉+炝炒圆白菜（含米饭）',
                    '孟维甫 186****5946'
                ];
     * @return string
     * @throws \Exception
     */
    public function printLabelContent(string $printerId, array $content): string
    {

        $rowCount = count($content);
        $firstRow = true;
        $lastRow = false;
        $formatContent = '';
        $fontSize = self::LABEL_FONT;
        $Y = self::LABEL_MARGIN_HIGH;
        foreach (array_values($content) as $key => $row) {
            // 判断是否是最后一行
            ($key + 1) == $rowCount && $lastRow = true;
            //获取 换行后的每一行
            $wrappedRow = self::_getWrappedRow($row);
            foreach ($wrappedRow as $r) {

                $wordWidth = mb_strwidth($r) * self::LABEL_WORD_HALF_WIDTH;
                if ($lastRow) { // 右对齐
                    $X = intval(self::LABEL_WIDTH - $wordWidth - self::LABEL_MARGIN_WIDTH);
                }
                else if($firstRow) { //居中
                    $X = intval((self::LABEL_WIDTH - self::LABEL_MARGIN_WIDTH * 2 - $wordWidth) / 2) + self::LABEL_MARGIN_WIDTH;
                }
                else { // 左对齐
                    $X =  self::LABEL_MARGIN_WIDTH;
                }

                $formatContent .= "<TEXT x=\"{$X}\" y=\"{$Y}\" font=\"{$fontSize}\" w=\"1\" h=\"1\" r=\"0\">{$r}</TEXT>";
                $firstRow = false;
                $Y += self::LABEL_FIELD_PADDING;
            }
            $Y += (self::LABEL_PADDING - self::LABEL_FIELD_PADDING);
        }

        $res = $this->request(self::API_LABEL_PRINT, [
            'sn'         => $printerId,
            'content'   => $formatContent,
            'times'     => 1,// 打印联数
        ]);
        if ($res['code'] == 0 && isset($res['response'])) {
            if ($res['response']['ret'] == 0) {
                return $res['response']['data'];
            }
            throw new \Exception($res['response']['msg']);
        }
        throw new \Exception("接口调用异常");
    }

    /**
     * 自动换行
     * @param string $row
     * @return array
     */
    private static function _getWrappedRow(string $row) : array
    {
        $wrappedRow = [];
        $XCapacity = self::LABEL_WIDTH - self::LABEL_MARGIN_WIDTH * 2;
        $wordWidth = mb_strwidth($row) * self::LABEL_WORD_HALF_WIDTH;

        if ($wordWidth > $XCapacity) {
            $begin = 0;
            for ($i = 1; $i <= mb_strlen($row); $i++) {
                $r =  mb_substr($row, $begin, $i - $begin);
                $rWidth = mb_strwidth($r) * self::LABEL_WORD_HALF_WIDTH;
                if ($rWidth > $XCapacity) {
                    $wrappedRow[] = mb_substr($row, $begin, $i - $begin - 1);
                    $begin = $i - 1;
                }
            }
            $wrappedRow[] = mb_substr($row, $begin);

        }
        else {
            $wrappedRow[] = $row;
        }

        return $wrappedRow;
    }

}