<?php
/**
 * Created by PhpStorm.
 * User: billy
 * Date: 18/03/2017
 * Time: 9:48 AM
 */

namespace App\Modules\Onenet\Message\ReceiveMessage;


use App\Common\Byte;
use App\Modules\Models\Machine\Machine;
use App\Modules\Onenet\Enum\DataStreams;
use App\Modules\Onenet\Message\MsgType;
use App\Modules\Onenet\Message\ReceiveMessage;
use Illuminate\Support\Facades\Log;

/**
 * Class BatteryMessage
 * @package App\Modules\Onenet\Message\ReceiveMessage
 */
class BatteryMessage extends ReceiveMessage
{
    /**
     * @var int
     */
    private $battery_count_stanza = 3;

    /**
     * @var int
     */
    private $position_status_stanza = 1;

    /**
     * @var int
     */
    private $battery_usage_stanza = 3;

    /**
     * @var int
     */
    private $battery_status_stanza = 1;

    /**
     * @var int
     */
    private $remark_stanza = 2;

    /**
     * @var
     */
    private $battery_count;

    /**
     * @var
     */
    private $battery_info;

    /**
     * @param $deviceId
     * BatteryMessage constructor.
     */
    public function __construct($deviceId)
    {
        parent::__construct($deviceId, MsgType::DATASTREAM_TYPE, DataStreams::BATTERY);
    }

    /**
     * @return mixed
     */
    public function getBatteryCount()
    {
        return $this->battery_count;
    }

    /**
     * @param mixed $battery_count
     */
    public function setBatteryCount($battery_count)
    {
        $this->battery_count = $battery_count;
    }

    /**
     * @return mixed
     */
    public function getBatteryInfo()
    {
        return $this->battery_info;
    }

    /**
     * @param mixed $battery_info
     */
    public function setBatteryInfo($battery_info)
    {
        $this->battery_info = $battery_info;
    }

    /**
     * @param $battery_total_count
     * @return int
     */
    private function getStanzaLength($battery_total_count)
    {
        return $this->battery_count_stanza
            + $battery_total_count * $this->getBatteryInfoLength()
            + $this->remark_stanza;
    }


    /**
     * @param $battery_total_count
     * @return int
     */
    private function getStanzaLengthWithoutRemark($battery_total_count)
    {
        return $this->battery_count_stanza
            + $battery_total_count * $this->getBatteryInfoLength();
    }

    /**
     * @return int
     */
    private function getBatteryInfoLength()
    {
        return $this->position_status_stanza
            + $this->battery_usage_stanza
            + $this->battery_status_stanza
            + config('constants.battery.sn_length');
    }

    private function getBatteryActualCount($msg)
    {
        return intval(substr($msg, 0, $this->battery_count_stanza));
    }


    /**
     * @param $msg
     */
    public function unpack($msg)
    {
        $device_id = $this->getDeviceId();

        Log::info('[BatteryMessage::unpack] device_id:'.$device_id);
        $machine = Machine::where('he_cloud_device_id', $device_id)->first();

        $battery_total_count = 0;
        if ($machine != null && $machine->count() > 0)
        {
            $battery_total_count = $machine->hatch_number;
        }

        Log::info('[BatteryMessage::unpack] msg:'.$msg);
        Log::info('>>>>Len($msg):'.strlen($msg));
        Log::info('>>>>getStanzaLength:'.$this->getStanzaLength($battery_total_count));
        Log::info('>>>>getStanzaLengthWithoutRemark:'.$this->getStanzaLengthWithoutRemark($battery_total_count));

        if (strlen($msg) != $this->getStanzaLength($battery_total_count) && strlen($msg) != $this->getStanzaLengthWithoutRemark($battery_total_count))
        {
            Log::error("[BatteryMessage::unpack] stanza size incorrect!, total size:".strlen($msg).",real size:".$this->getStanzaLength($battery_total_count));
            return;
        }

        if ($this->getBatteryActualCount($msg) > $battery_total_count)
        {
            Log::error("[BatteryMessage::unpack] inside battery count error!");
            return;
        }

        //get inside box battery count
        $temp_battery_count = $this->getBatteryActualCount($msg);

        $realBatteryCount = 0;
        $temp_battery_info = array();
        $msg = substr($msg, $this->battery_count_stanza);

        for ($i = 0; $i < $battery_total_count; $i++)
        {
            //check if has Battery is correct
            $hasBattery = intval($msg[$i*$this->getBatteryInfoLength()]);
            if ($hasBattery == 1 )
            {
                $realBatteryCount++;
            }
            else if ($hasBattery == 0)
            {
                continue;
            }
            else
            {
                Log::error("[BatteryMessage::unpack] has battery is not correct!");
                return;
            }

            $battery = new BatteryInfo();

            $battery->setPosition($i+1);

            //check if battery life is correct
            $battery_life = intval(substr($msg, $i*$this->getBatteryInfoLength() + 1, $this->battery_usage_stanza));
            if ( $battery_life <= 100 || $battery_life >=0)
            {
                $battery->setBatteryLife($battery_life);
            }
            else
            {
                Log::error("[BatteryMessage::unpack] has battery is not correct!");
                return;
            }

            //check battery status
            $battery->setStatus(1);

            //getBattery Sn
            $sn = substr($msg,$i*$this->getBatteryInfoLength() + $this->battery_usage_stanza + 2, config('constants.battery.sn_length'));
            $battery->setBatterySn($sn);

            array_push($temp_battery_info, $battery);
        }

        if($realBatteryCount != $temp_battery_count)
        {
            Log::error("[BatteryMessage::unpack] real battery count is incorrect!");
            return;
        }

        $this->battery_count = $temp_battery_count;
        $this->battery_info = $temp_battery_info;
    }
}