<?php

namespace Ignite\Core\Models\Form;

use Exception;
use Illuminate\Support\Arr;

trait GroupByTableTrait
{
    /**
     * Groups that are pre-determined as being 'backend' only.
     *
     * @var array
     */
    protected $backendGroups = ['internal', 'admin', 'account'];

    /**
     * Storage for existing groups for the form.
     *
     * @var array
     */
    protected $groups = [];

    /**
     * Extract the group and add it to the local cache.
     *
     * @param array $field
     */
    protected function extractGroup(array $field)
    {
        if (! array_key_exists('name', $field)) {
            return;
        }

        $name = $field['name'];
        $group = Arr::pull($field, 'group');

        if (! isset($this->groups[$group])) {
            $this->groups[$group] = [];
        }

        $this->groups[$group][$name] = $field;
    }

    /**
     * Render groups.
     *
     * @param  array $schema
     *
     * @throws Exception
     */
    protected function renderGroups(array $schema)
    {
        $groups = Arr::get($schema, 'groups', []);

        foreach ($this->groups as $group => $fields) {
            if (in_array($group, $this->backendGroups)) {
                if ($this->isViewingBackend()) {
                    $this->renderGroup($group, $fields, $groups);
                    continue;
                }
            } else {
                $this->renderGroup($group, $fields, $groups);
            }
        }
    }

    /**
     * Render a group.
     *
     * @param string $group
     * @param array $fields
     * @param array $groups
     *
     * @throws Exception
     */
    protected function renderGroup($group, $fields, $groups)
    {
        $groupName = "group_$group";
        $meta = Arr::get($groups, $group, []);

        $this->addBefore('submit', $groupName, 'static', [
            'label_attr' => ['class' => 'group-heading'],
            'wrapper' => ['class' => 'group-container'],
            'tag' => 'div',
            'attr' => [
                'class' => 'form-control-static' . Arr::has($meta, 'value') ? '' : ' hidden'
            ],
            'label' => __(Arr::get($meta, 'label', ucwords($group))),
            'value' => Arr::get($meta, 'value', '')
        ]);

        $last = $groupName;

        foreach ($fields as $name => $field) {
            $this->renderField($field, $last);
            $last = $name;
        }
    }

    /**
     * Group the values by their associated tables.
     *
     * @param  array $values
     * @return array
     */
    protected function groupByTable($values)
    {
        $grouped = [];
        foreach ($values as $name => $value) {
            $field = $this->getField($name);
            $table = $field->getOption('table');

            if (! isset($grouped[$table])) {
                $grouped[$table] = [];
            }

            $grouped[$table][$name] = $value;
        }

        return $grouped;
    }

    abstract protected function isViewingBackend();

    abstract protected function renderField(array $field, $after = null);

    abstract public function addBefore($name, $fieldName, $type = 'text', $options = [], $modify = false);
}
