<?php


namespace Lackoxygen\GzCbec\Traits;

use Illuminate\Support\Arr;
use Illuminate\Support\Collection as BaseCollection;
use Lackoxygen\GzCbec\Contract\XMLInterface;
use Lackoxygen\GzCbec\Exception\Exception;
use Lackoxygen\GzCbec\Constant\XML as xmlConstant;

trait XML
{
    /**
     * @throws Exception
     */
    public function toXML(string $head): string
    {
        if (!$this instanceof BaseCollection) {
            throw new Exception('not support');
        }
        $simpleXML = new \SimpleXMLElement(xmlConstant::FIRST_LINE . $head);
        $this->arrayToXML($this->toArray(), $simpleXML);

        return $simpleXML->asXML();
    }

    /**
     * @param \SimpleXMLElement $xmlObj
     * @param                   $key
     * @param null              $value
     */
    protected function appendChildToXMl(\SimpleXMLElement $xmlObj, $key, $value = null): \SimpleXMLElement
    {
        if ($this instanceof XMLInterface) {
            $key = $this->getFirstLabelPrefix() . ':' . $key;
        }
        if (is_null($value)) {
            //$xmlObj->addChild($key);
        } else {
            $xmlObj->addChild($key, $value);
        }

        return $xmlObj;
    }

    /**
     * @param                   $array
     * @param \SimpleXMLElement $xmlObj
     */
    protected function arrayToXML($array, \SimpleXMLElement &$xmlObj)
    {
        foreach ($array as $key => $value) {
            if (is_numeric($key)) {
                $key = Arr::get($value, '__last_key');
                unset($value['__last_key']);
            }
            if (is_array($value) || is_object($value)) {
                if (Arr::exists($value, 0)) {
                    foreach ($value as &$item) {
                        Arr::set($item, '__last_key', $key);
                    }
                    $this->appendChildToXMl($xmlObj, $key);
                    $this->arrayToXML($value, $xmlObj);
                } else {
                    $subNode = $xmlObj->addChild($key);
                    $this->arrayToXML($value, $subNode);
                }
            } else {
                $this->appendChildToXMl($xmlObj, $key, $value);
            }
        }
    }
}