<?php

namespace xmvc;

/**
 * MetaTree 树基类
 */
abstract class BaseMetaTree extends BaseMeta
{
    /** ID 值 value */
    protected mixed $vId;
    /** 父ID 值 */
    protected mixed $vParentId;
    /** 层级 值 */
    protected int $vLevel;
    /** 是否是终节点 值 */
    protected bool $vIsEnd;
    /** 序号 值 */
    protected int $vSort;
    /** 路径 值, 存储的时末尾要加逗号 (索引考虑) */
    protected ?string $vFullPath;
    /** 路径 值 */
    protected ?array $vFullPathArr;
    /** 左值 值 可为空, 当不为空时将使用 左右值树逻辑 */
    protected int $vLeft;
    /** 右值 值 可为空, 当不为空时将使用 左右值树逻辑 */
    protected int $vRight;

    /** 子节点 */
    public array $childrens;

    // 路径分解成数组
    public function splitFullPath(): ?array
    {
        if (!$this->vFullPath) {
            return null;
        }
        if (!isset($this->vFullPathArr)) {
            $this->vFullPathArr = explode(',', $this->vFullPath);
            foreach ($this->vFullPathArr as $key => $value) {
                if ($value) {
                    $this->vFullPathArr[$key] = (int)$value;
                }
            }
        }
        return $this->vFullPathArr;
    }

    /**
     * 取根节点
     *
     * @return static
     */
    public function getRoot(): ?self
    {
        if ($this->vParentId == static::$rootNodeParentValue || $this->vLevel == 0) {
            return null;
        }
        if ($this->vLevel == 1) {
            return $this->getParent();
        }
        $rootId = substr($this->vFullPath, 0, strpos($this->vFullPath, ','));
        return $rootId ? static::get($rootId) : null;
    }

    /**
     * 取父节点
     *
     * @return self
     */
    public function getParent(): ?self
    {
        if (!$this->vFullPath) {
            return null;
        }
        $q = static::getSqler();
        $row = $q->table(static::$baseTableName)
            ->where(static::$fId, $this->vParentId)
            ->row();
        return $row ? static::fromDBRow($row) : null;
    }

    /**
     * 取所有父节点
     *
     * @return array
     */
    public function getAllParents(): ?array
    {
        if (!$this->vFullPath) {
            return null;
        }
        $result = [];
        $fullPathArr = $this->splitFullPath();
        $q = $this->getSqler();
        $rows = $q->table(static::$baseTableName)
            ->where(static::$fId, $fullPathArr)
            ->orderBy(static::$fId, $fullPathArr)
            ->all();
        foreach ($rows as $row) {
            $result[] = static::fromDBRow($row);
        }
        return $result;
    }

    /**
     * 取子节点
     *
     * @return array
     */
    public function getChildrens(): array
    {
        $this->childrens = [];
        if ($this->vIsEnd) {
            return [];
        }
        $q = static::getSqler();
        $rows = $q->table(static::$baseTableName)
            ->where(static::$fParentId, $this->vId)
            ->orderBy(static::$fSort)
            ->all();
        foreach ($rows as $i => $row) {
            $this->childrens[] = static::fromDBRow($row);
        }
        return $this->childrens;
    }

    /**
     * 取所有子节点, 树型展开结构 (递归查询)
     *
     * @return array
     */
    public function getChildrensTree(): array
    {
        $this->getChildrens();
        foreach ($this->childrens as $children) {
            $children->getChildrensTree();
        }
        return $this->childrens;
    }
    /**
     * 取所有子节点, 数组结构 (fullPath 查询)
     *
     * @return array
     */
    public function getChildrensList(): array
    {
        $newFullPath = $this->vFullPath ? $this->vFullPath . $this->vId : $this->vId;
        $newFullPath .= ',';
        $q = static::getSqler();
        $rows = $q->table(static::$baseTableName)
            ->where(static::$fFullPath . '{=%}', $newFullPath)
            ->orderBy([static::$fLevel, static::$fFullPath, static::$fSort])
            ->all();
        foreach ($rows as $row) {
            $result[] = static::fromDBRow($row);
        }
        return $result;
    }
}
