<?php

namespace helpers;

abstract class xlvask_helper
{
    /**
     * Convert the helper object to an array representation.
     * This method returns an associative array containing all non-private properties of the object.
     * @return array
     */
    public function toArray(): array
    {
        return array_filter(
            get_object_vars($this),
            function ($property) {
                return !str_starts_with($property, "\0");
            },
            ARRAY_FILTER_USE_KEY
        );
    }

    /**
     * Convert an array to objects
     * @param array $array The array containing the data to populate objects with.
     * @returns object[]
     */
    public function toObjects(array $array): array
    {
        return array_map(function ($item) {
            $object = new static();
            $object->populate($item);
            return $object;
        }, $array);
    }

    /**
     * Populate class
     * @param array $array
     * @returns void
     */
    public function populate(array $array): void
    {
        foreach ($array as $property => $value) {
            if (property_exists($this, $property)) {
                $this->$property = $value;
            }
        }
    }

    /**
     * Debug print object details
     * @returns string
     */
    public function formattedDetails(): string
    {
        $tmp = "Class: " . get_class($this) . "\n";
        $tmp .= "Properties: \n";
        foreach ($this as $property => $value) {
            $tmp .= "  - $property: $value\n";
        }
        $tmp .= "Methods: \n";
        foreach (get_class_methods($this) as $method) {
            $tmp .= "  - $method\n";
        }
        $tmp .= "Other: \n";
        if (method_exists($this, 'getMissingRequiredProperties') && count($this->getMissingRequiredProperties()) > 0) {
            $tmp .= "  - missingRequiredProperties: " . implode(', ', $this->getMissingRequiredProperties()) . "\n";
        }
        if (method_exists($this, 'isValid')) {
            $tmp .= "  - isValid: " . ($this->isValid() ? 'true' : 'false') . "\n";
        }
        return $tmp;
    }

    /**
     * Default is valid
     */
    public function isValid(): bool
    {
        return true;
    }
}