<?php

namespace SilverStripe\UserForms\Model\EditableFormField;

use SilverStripe\Forms\CheckboxField;
use SilverStripe\Forms\TextField;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\GridField\GridFieldButtonRow;
use SilverStripe\Forms\GridField\GridFieldConfig;
use SilverStripe\Forms\GridField\GridFieldDeleteAction;
use SilverStripe\Forms\GridField\GridFieldToolbarHeader;
use SilverStripe\Forms\Tab;
use SilverStripe\ORM\Map;
use SilverStripe\UserForms\Model\EditableFormField;
use SilverStripe\Versioned\Versioned;
use Symbiote\GridFieldExtensions\GridFieldAddNewInlineButton;
use Symbiote\GridFieldExtensions\GridFieldEditableColumns;
use Symbiote\GridFieldExtensions\GridFieldOrderableRows;
use Symbiote\GridFieldExtensions\GridFieldTitleHeader;

/**
 * Base class for multiple option fields such as {@link EditableDropdownField}
 * and radio sets.
 *
 * Implemented as a class but should be viewed as abstract, you should
 * instantiate a subclass such as {@link EditableDropdownField}
 *
 * @see EditableCheckboxGroupField
 * @see EditableDropdownField
 *
 * @package userforms
 */

class EditableMultipleOptionField extends EditableFormField
{
    /**
     * Define this field as abstract (not inherited)
     *
     * @config
     * @var bool
     */
    private static $abstract = true;

    private static $has_many = [
        'Options' => EditableOption::class,
    ];

    private static $owns = [
        'Options',
    ];

    private static $cascade_deletes = [
        'Options',
    ];

    private static $table_name = 'EditableMultipleOptionField';

    /**
     * @return \SilverStripe\Forms\FieldList
     */
    public function getCMSFields()
    {
        $this->beforeUpdateCMSFields(function ($fields) {
            $editableColumns = new GridFieldEditableColumns();
            $editableColumns->setDisplayFields([
                'Title' => [
                    'title' => _t(__CLASS__.'.TITLE', 'Title'),
                    'callback' => function ($record, $column, $grid) {
                        return TextField::create($column);
                    }
                ],
                'Value' => [
                    'title' => _t(__CLASS__.'.VALUE', 'Value'),
                    'callback' => function ($record, $column, $grid) {
                        return TextField::create($column);
                    }
                ],
                'Default' => [
                    'title' => _t(__CLASS__.'.DEFAULT', 'Selected by default?'),
                    'callback' => function ($record, $column, $grid) {
                        return CheckboxField::create($column);
                    }
                ]
            ]);

            $optionsConfig = GridFieldConfig::create()
                ->addComponents(
                    new GridFieldToolbarHeader(),
                    new GridFieldTitleHeader(),
                    new GridFieldOrderableRows('Sort'),
                    $editableColumns,
                    new GridFieldButtonRow(),
                    new GridFieldAddNewInlineButton(),
                    new GridFieldDeleteAction()
                );

            $optionsGrid = GridField::create(
                'Options',
                _t('SilverStripe\\UserForms\\Model\\EditableFormField.CUSTOMOPTIONS', 'Options'),
                $this->Options(),
                $optionsConfig
            );

            $fields->insertAfter(Tab::create('Options', _t(__CLASS__.'.OPTIONSTAB', 'Options')), 'Main');
            $fields->addFieldToTab('Root.Options', $optionsGrid);
        });

        $fields = parent::getCMSFields();

        return $fields;
    }

    /**
     * Duplicate a pages content. We need to make sure all the fields attached
     * to that page go with it
     *
     * {@inheritDoc}
     */
    public function duplicate($doWrite = true, $manyMany = 'many_many')
    {
        // Versioned 1.0 has a bug where [] will result in _all_ relations being duplicated
        if ($manyMany === 'many_many' && !$this->manyMany()) {
            $manyMany = null;
        }

        $clonedNode = parent::duplicate(true, $manyMany);

        foreach ($this->Options() as $field) {
            /** @var EditableOption $newField */
            $newField = $field->duplicate(false);
            $newField->ParentID = $clonedNode->ID;
            $newField->Version = 0;
            $newField->write();
        }

        return $clonedNode;
    }

    /**
     * Return whether or not this field has addable options such as a
     * {@link EditableDropdown} or {@link EditableRadioField}
     *
     * @return bool
     */
    public function getHasAddableOptions()
    {
        return true;
    }

    /**
     * Gets map of field options suitable for use in a form
     *
     * @return array
     */
    protected function getOptionsMap()
    {
        $optionSet = $this->Options();
        $optionMap = $optionSet->map('Value', 'Title');
        if ($optionMap instanceof Map) {
            return $optionMap->toArray();
        }
        return $optionMap;
    }

    /**
     * Returns all default options
     *
     * @return \SilverStripe\ORM\SS_List
     */
    protected function getDefaultOptions()
    {
        return $this->Options()->filter('Default', 1);
    }
}