<?php
/**
 * Created by PhpStorm.
 * User: billy
 * Date: 30/08/2017
 * Time: 10:18 AM
 */
namespace App\Modules\Onenet;

use App\Common\TencentMQ\HttpProducer;
use App\Modules\Onenet\Enum\Commands;
use App\Modules\Onenet\Message\CommandMessage;
use Illuminate\Support\Facades\Log;

/**
 * Class Onenet
 * @package App\Modules\Onenet
 */
class Onenet
{
    /**
     * @param $consume_order_id
     * @param $topic
     * @return mixed
     */
    public function produceMessage($consume_order_id, $topic)
    {
        $http_producer = new HttpProducer(config('constants.mq.host'),
            config('constants.mq.secret_id'),
            config('constants.mq.secret_key'));

        $result = $http_producer->sendMessage($topic, 'orderId:'.$consume_order_id,40);

        Log::info("produce message result is : " . json_encode($result));
        return $result;
    }


    /**
     * @param $machine
     * @param $position
     * @param $order_id
     * @return bool
     */
    public function open($machine, $order_id, $position)
    {
//        $commandMessage = new CommandMessage($machine->he_cloud_device_id,0x76, [sprintf("%02d", intval($position-1))]);
        $commandMessage = new CommandMessage($machine->he_cloud_device_id,chr(0x76), [$position-1]);

        $onenetApi = new OnenetApi();

        $result = $onenetApi->send_data_to_edp($commandMessage->getDeviceId(), 1, 0, $commandMessage->pack());

        if (empty($result) || !empty($result['errno'])) {
            return false;
        }

        $this->produceMessage($order_id, config('constants.mq.open_topic'));


        return true;
    }

    /**
     * @param $machine
     * @param $order_id
     * @param $positions
     * @return bool
     */
    public function openMultiple($machine, $order_id, $positions)
    {

        $command = 'Slt=';

        $count = count($positions);
        $command .= chr($count);

        foreach ($positions as $position)
        {
            $command .= chr($position);
        }

        $command .= '|';


        $hexTime = dechex(time() + 28800);
//        $hexTime = dechex(time());
        Log::info('[request onenet]: '.(time() + 28800));
        for ($i =0 ; $i < 4; $i++)
        {
            $command .= chr(hexdec(substr($hexTime, 2 * $i, 2)));
        }
        $command .= '0000';

        $commandMessage = new CommandMessage($machine->he_cloud_device_id, $command, []);

        $onenetApi = new OnenetApi();

        $result = $onenetApi->send_data_to_edp($commandMessage->getDeviceId(), 1, 0, $commandMessage->pack());

        if (empty($result) || !empty($result['errno'])) {
            return false;
        }

        $this->produceMessage($order_id, config('constants.mq.open_topic'));

        return true;
    }


    /**
     * @param $machine_he_cloud_device_id
     * @return bool
     */
    public function switchPlatform($machine_he_cloud_device_id)
    {
        $commandMessage = new CommandMessage($machine_he_cloud_device_id, Commands::SWITCH_PLATFORM, []);

        $onenetApi = new OnenetApi();

        $result = $onenetApi->send_data_to_edp($machine_he_cloud_device_id, 1, 0, $commandMessage->pack());

        if (empty($result) || !empty($result['errno'])) {
            return false;
        }

        return true;
    }

    /**
     * @param $title
     * @param $auth_info
     * @param string $desc
     * @return array
     */
    private function buildDevice($title, $auth_info, $desc="")
    {
        return array(
            'title' => $title,
            'desc' => $desc,
            'private' => true,
            'protocol' => 'EDP',
            'auth_info' => $auth_info
        );
    }

    /**
     * @param $deviceId
     * @return array
     */
    public function deviceAdd($deviceId)
    {
        $onenetApi = new OnenetApi();
        $result = $onenetApi->device_add($this->buildDevice($deviceId, $deviceId));

        if(!empty($result) && empty($result['errno']))
        {
            return ['result' => true, 'he_cloud_device_id' => $result['data']['device_id']];
        }
        else
        {
            return ['result' => false];
        }
    }

    /**
     * @param $heCloudDeviceId
     * @return bool
     */
    public function deviceDelete($heCloudDeviceId)
    {
        $onenetApi = new OnenetApi();
        $result = $onenetApi->device_delete($heCloudDeviceId);

        if(!empty($result) && empty($result['errno']))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    /**
     * @param $msg
     * @return bool|string
     */
    public function decryptMessage($msg)
    {
        $EncodingAESKey = config('constants.heCloud.encoding_aes_key');

        $aeskey = base64_decode($EncodingAESKey."=");
        $aes_message = base64_decode($msg);

        $decrypted_message = openssl_decrypt($aes_message, 'aes-256-cbc', $aeskey, OPENSSL_RAW_DATA, substr($aeskey, 0, 16));

        $decrypted_message = substr($decrypted_message, 16);

        $lengthStr = substr($decrypted_message, 0,4);

        $length = 0;
        for ($i = 0; $i<strlen($lengthStr); $i++)
        {
            $length += ord($lengthStr[$i]) * pow(2, (3-$i) * 8);
        }

        $decrypted_message = substr($decrypted_message, 4, $length);

        if ($decrypted_message === false)
        {
            $decrypted_message = '';
        }

        return $decrypted_message;
    }

    /**
     * @param $msg
     * @param $nonce
     * @param $signature
     * @return bool
     */
    public function checkSignature($msg, $nonce, $signature)
    {
        $str = config('constants.heCloud.token').$nonce.$msg;
        $str = md5($str, true);
        $sig = base64_encode($str);

        return $sig === $signature;
    }
}