<?php

namespace apexl\Io\modules\formbuilder\entities;

use apexl\Io\includes\Entity;
use apexl\Io\modules\formbuilder\interfaces\formFieldInterface;

class formEntity extends Entity
{
    protected $fields;
    protected $form_details;

    protected $fieldObjects;
    protected $validations = [];

    /** @todo, do this better */

    public function __construct()
    {
        parent::__construct('forms');
        $this->fields = (object) [];
        $this->form_details = (object) [];
        $this->callBackData = (object) [];
        $this->formVerb(); //default to POST
    }

    /**
     * Since api forms could use Axios, we can set non traditional HTTP Verbs for form submission.
     * @param  bool  $verb
     * @return $this
     */
    public function formVerb($verb = 'POST')
    {
        $this->form_details->verb = strtoupper($verb);

        return $this;
    }

    /**
     * @param  bool  $fieldset
     * @return $this
     */
    public function addField(formFieldInterface $field, $fieldset = false)
    {
        if ($fieldset) {
            $this->addFieldToFieldset($field, $fieldset);
        } else {
            $this->fields->{$field->field->name} = $field->field;
        }
        $this->fieldObjects[$field->field->name] = $field;
        $this->validations[$field->field->name] = $field->field->validations ?? null;

        return $this;
    }

    public function addFieldToFieldset($field, $fieldset = false)
    {
        $fieldsetId = $this->checkGenerateFieldset($fieldset);
        $this->fields->$fieldsetId->{$field->field->name} = $field->field;
        $this->validations[$field->field->name] = $field->field->validations ?? null;

        return $this;
    }

    protected function checkGenerateFieldset($fieldset)
    {
        $fieldsetId = 'fieldset_'.strtolower(str_replace('_', '', (string) $fieldset));
        if (!isset($this->fields->$fieldsetId)) {
            $this->fields->$fieldsetId = (object) [];
        }

        return $fieldsetId;
    }

    public function addFieldToGroup(formFieldInterface $field, $group, $fieldset = false)
    {
        $fieldGroup = 'fieldGroup_'.strtolower(str_replace('_', '', (string) $group));
        if ($fieldset) {
            $this->addFieldGroupToFieldset($field, $fieldGroup, $fieldset);
        } else {
            $this->fields->$fieldGroup[$field->field->name] = $field->field;
        }
        $this->validations[$field->field->name] = $field->field->validations ?? null;

        return $this;
    }

    public function addFieldGroupToFieldset($field, $fieldGroup, $fieldset = false)
    {
        $fieldsetId = $this->checkGenerateFieldset($fieldset);
        if (!isset($this->fields->$fieldsetId->$fieldGroup)) {
            $this->fields->$fieldsetId->$fieldGroup = (object) [];
        }
        $this->fields->$fieldsetId->$fieldGroup->{$field->field->name} = $field->field;

        return $this;
    }

    public function addFieldGroupClasses($group, $classes)
    {
        $fieldGroup = 'fieldGroup_'.strtolower(str_replace('_', '', (string) $group));
        //@todo check if this is in a fieldset.
        if (isset($this->fields->$fieldGroup)) {
            $this->fields->$fieldGroup['__classes'] = $classes;
        }

        return $this;
    }

    public function setFieldsetSetting($fieldset, $setting, $value)
    {
        $fieldsetId = $this->checkGenerateFieldset($fieldset);
        if (!isset($this->fields->$fieldsetId->fieldset_settings)) {
            $this->fields->$fieldsetId->fieldset_settings = (object) [];
        }
        $this->fields->$fieldsetId->fieldset_settings->$setting = $value;
    }

    protected function setId($id)
    {
        $this->form_details->id = $id;

        return $this;
    }

    public function addClass($class)
    {
        $this->form_details->classes[] = $class;

        return $this;
    }

    public function setMethod($method)
    {
        $this->formVerb($method);

        return $this;
    }

    public function setActionUrl($action)
    {
        $this->form_details->action = $action;

        return $this;
    }

    public function setSubmitText($text)
    {
        $this->form_details->submit = $text;

        return $this;
    }

    public function includeClearButton($include = true)
    {
        $this->form_details->clearButton = $include;

        return $this;
    }

    public function setClearButtonText($text)
    {
        $this->form_details->clearButtonText = $text;

        return $this;
    }

    public function removeSubmitButton($remove = true)
    {
        $this->form_details->removeSubmit = $remove;

        return $this;
    }

    public function submitAsFormData($asFormData = true)
    {
        $this->form_details->isFormData = $asFormData;

        return $this;
    }

    public function getFields()
    {
        return $this->fields;
    }

    public function getDetails()
    {
        return $this->form_details;
    }

    public function getFormField($name): formFieldInterface|false
    {
        return $this->fieldObjects[$name] ?? false;
    }

    public function deleteField($name)
    {
        unset($this->fields->$name);

        return $this;
    }

    public function getBuiltFormArray()
    {
        return [
            "form" => [
                "details" => $this->form_details,
                "fields" => $this->fields,
                "callBackData" => $this->callBackData,
                "validations" => $this->getValidationsConfig(),
            ],
        ];
    }

    public function getAsJson()
    {
        return json_encode((object) $this->data);
    }

    public function addCallbackData($fieldName, $data)
    {
        $this->callBackData->$fieldName = $data;

        return $this;
    }

    public function removeField(string $name): formEntity
    {
        if (isset($this->fields->$name)) {
            unset($this->fields->$name);
        }

        return $this;
    }

    public function getValidationsConfig()
    {
        $validations = (object)[];
        foreach ($this->validations as $fieldName => $validation) {
            $validations->$fieldName = (object)$validation;
        }


        return $this->validations;
    }
}
