<?php
namespace SabaiApps\Directories\Component\View\Helper;

use SabaiApps\Directories\Application;
use SabaiApps\Directories\Component\Entity;
use SabaiApps\Directories\Component\Form;
use SabaiApps\Directories\Component\Display\Controller\Admin\AddDisplay;

class FeatureSettingsFormHelper
{
    public function help(Application $application, Entity\Model\Bundle $bundle, array $featuresDisabledByMode, array $settings = [], $isDefaultView = false, array $submitValues = null)
    {
        $states = [];
        foreach ($featuresDisabledByMode as $view_mode => $view_features) {
            foreach ($view_features as $feature_name) {
                $states[$feature_name][] = $view_mode;
            }
        }

        $form = [
            '#tabs' => [],
            '#validate' => [
                function ($form) use ($featuresDisabledByMode) {
                    $mode_selected = $form->values['general']['mode'];
                    if (!empty($featuresDisabledByMode[$mode_selected])) {
                        foreach ($featuresDisabledByMode[$mode_selected] as $feature_disabled) {
                            unset($form->values[$feature_disabled]);
                        }
                    }
                },
            ],
        ];
        $features = [
            'sort' => [
                'label' => __('Sort Settings', 'directories'),
                'weight' => 5,
            ],
            'pagination' => [
                'label' => _x('Pagination', 'tab', 'directories'),
                'weight' => 10,
            ],
            'query' => [
                'label' => __('Query Settings', 'directories'),
                'weight' => 15,
            ],
            'filter' => [
                'label' => __('Filter Settings', 'directories'),
                'weight' => 20,
            ],
            'other' => [
                'label' => __('Other', 'directories'),
                'weight' => 25,
            ],
        ];
        foreach ($features as $feature_name => $feature) {
            if (!$feature_settings_form = $this->_getViewFeatureSettingsForm(
                $application,
                $bundle,
                $feature_name,
                isset($settings[$feature_name]) ? $settings[$feature_name] : [],
                $isDefaultView,
                [$feature_name],
                isset($submitValues[$feature_name]) ? $submitValues[$feature_name] : null
            )) continue;

            $form[$feature_name] = [
                '#tree' => true,
                '#tabs' => [
                    $feature_name => [
                        '#title' => $feature['label'],
                        '#weight' => $feature['weight'],
                    ],
                ],
                '#tab' => $feature_name,
            ] + $feature_settings_form;
            if (!empty($states[$feature_name])) {
                $form[$feature_name]['#states']['invisible']['[name="general[mode]"]']
                    = $form[$feature_name]['#tabs'][$feature_name]['#states']['invisible']['[name="general[mode]"]']
                    = ['type' => 'one', 'value' => $states[$feature_name]];
            }
        }

        return $application->Filter('view_feature_settings_form', $form, [$bundle, $settings, $submitValues]);
    }

    protected function _getViewFeatureSettingsForm(Application $application, Entity\Model\Bundle $bundle, $feature, array $settings, $isDefaultView, array $parents, array $submitValues = null)
    {
        switch ($feature) {
            case 'sort':
                $form = [
                    '#element_validate' => array(array($this, '_validateSort')),
                    'default' => array(
                        '#type' => 'select',
                        '#default_value' => isset($settings['default']) ? $settings['default'] : null,
                        '#title' => __('Default sort order', 'directories'),
                        '#options' => $this->_getSortOptions($application, $bundle),
                        '#required' => true,
                        '#display_unrequired' => true,
                        '#horizontal' => true,
                        '#weight' => 5,
                    ),
                    'secondary' => array(
                        '#type' => 'select',
                        '#default_value' => isset($settings['secondary']) ? $settings['secondary'] : null,
                        '#title' => __('Secondary sort order', 'directories'),
                        '#options' => ['' => __('— Select —', 'directories')] +  $this->_getSortOptions($application, $bundle),
                        '#required' => false,
                        '#horizontal' => true,
                        '#weight' => 6,
                    ),
                    'options' => array(
                        '#type' => 'sortablecheckboxes',
                        '#options' => $sorts = $this->_getSortOptions($application, $bundle, true),
                        '#option_no_escape' => true,
                        '#default_value' => isset($settings['options']) ? $settings['options'] : array(current(array_keys($sorts))),
                        '#title' => __('Sort options', 'directories'),
                        '#horizontal' => true,
                        '#weight' => 1,
                    ),
                ];
                if ($application->Entity_BundleTypeInfo($bundle, 'featurable')) {
                    $form['stick_featured'] = [
                        '#type' => 'checkbox',
                        '#title' => __('Show featured items first', 'directories'),
                        '#default_value' => !empty($settings['stick_featured']),
                        '#horizontal' => true,
                        '#weight' => 10,
                    ];
                    if ($isDefaultView) {
                        $form['stick_featured_term_only'] = [
                            '#type' => 'checkbox',
                            //'#switch' => false,
                            '#title' => __('Show featured items first on single term pages only', 'directories'),
                            '#default_value' => !empty($settings['stick_featured_term_only']),
                            '#horizontal' => true,
                            '#weight' => 11,
                            '#states' => array(
                                'visible' => array(
                                    sprintf('input[name="%s"]', $application->Form_FieldName(array_merge($parents, ['stick_featured']))) => ['type' => 'checked', 'value' => true]
                                ),
                            ),
                        ];
                    }
                }
                return $form;

            case 'pagination':
                $no_pagination_selector = sprintf('input[name="%s"]', $application->Form_FieldName(array_merge($parents, ['no_pagination'])));
                $type_selector = sprintf('select[name="%s"]', $application->Form_FieldName(array_merge($parents, ['type'])));
                return [
                    'no_pagination' => [
                        '#type' => 'checkbox',
                        '#title' => __('Disable pagination', 'directories'),
                        '#default_value' => !empty($settings['no_pagination']) || (!isset($settings['no_pagination']) && !empty($bundle->info['internal'])),
                        '#horizontal' => true,
                        '#weight' => 1,
                    ],
                    'type' => [
                        '#type' => 'select',
                        '#title' => __('Pagination type', 'directories'),
                        '#options' => [
                            '' => __('Default', 'directories'),
                            'load_more' => __('Load more button', 'directories'),
                        ],
                        '#default_value' => isset($settings['type']) ? $settings['type'] : '',
                        '#states' => array(
                            'visible' => array(
                                $no_pagination_selector => ['type' => 'checked', 'value' => false],
                                '[name="general[mode]"]' => ['type' => 'one', 'value' => ['list', 'table']],
                            ),
                        ),
                        '#horizontal' => true,
                        '#weight' => 3,
                    ],
                    'perpage' => [
                        '#type' => 'slider',
                        '#title' => __('Items per page', 'directories'),
                        '#default_value' => isset($settings['perpage']) ? $settings['perpage'] : 20,
                        '#integer' => true,
                        '#required' => true,
                        '#display_unrequired' => true,
                        '#max_value' => $application->Filter('view_feature_settings_pagination_perpage_max', 120, [$bundle, $isDefaultView]),
                        '#min_value' => 1,
                        '#horizontal' => true,
                        '#states' => array(
                            'visible' => array(
                                $no_pagination_selector => ['type' => 'checked', 'value' => false],
                            ),
                        ),
                        '#weight' => 5,
                    ],
                    'allow_perpage' => [
                        '#type' => 'checkbox',
                        '#title' => __('Allow selection of number of items per page', 'directories'),
                        '#default_value' => !empty($settings['allow_perpage']),
                        '#horizontal' => true,
                        '#states' => array(
                            'visible' => array(
                                $no_pagination_selector => ['type' => 'checked', 'value' => false],
                                $type_selector => ['value' => ''],
                            ),
                        ),
                        '#weight' => 10,
                    ],
                    'perpages' => [
                        '#type' => 'checkboxes',
                        '#integer' => true,
                        '#title' => __('Allowed number of items per page', 'directories'),
                        '#default_value' => isset($settings['perpages']) ? $settings['perpages'] : array(10, 20, 50),
                        '#options' => array_combine($perpages = $application->Filter('view_pagination_perpages', array(10, 12, 15, 20, 24, 30, 36, 48, 50, 60, 100, 120, 200)), $perpages),
                        '#horizontal' => true,
                        '#states' => array(
                            'visible' => array(
                                $no_pagination_selector => ['type' => 'checked', 'value' => false],
                                $type_selector => ['value' => ''],
                                sprintf('input[name="%s"]', $application->Form_FieldName(array_merge($parents, ['allow_perpage']))) => ['type' => 'checked', 'value' => true],
                            ),
                        ),
                        '#weight' => 15,
                        '#columns' => 6,
                    ],
                    'load_more_label' => [
                        '#type' => 'textfield',
                        '#title' => __('Custom "Load More" button label', 'directories'),
                        '#states' => array(
                            'visible' => array(
                                $no_pagination_selector => ['type' => 'checked', 'value' => false],
                                $type_selector => ['value' => 'load_more'],
                            ),
                        ),
                        '#horizontal' => true,
                        '#weight' => 5,
                        '#placeholder' => __('Load More', 'directories'),
                        '#default_value' => isset($settings['load_more_label']) ? $settings['load_more_label'] : '',
                    ],
                ];
            case 'filter':
                if (!$application->getComponent('View')->isFilterable($bundle)) return;

                $show_filters_selector = sprintf('input[name="%s"]', $application->Form_FieldName(array_merge($parents, ['show'])));
                $show_in_modal_selector = sprintf('input[name="%s"]', $application->Form_FieldName(array_merge($parents, ['show_modal'])));
                $ret = [
                    '#element_validate' => array(array($this, '_validateFilter')),
                    'show' => [
                        '#type' => 'checkbox',
                        '#title' => __('Show filter form', 'directories'),
                        '#default_value' => !empty($settings['show']),
                        '#horizontal' => true,
                        '#weight' => 5,
                    ],
                    'shown' => [
                        '#type' => 'checkbox',
                        '#title' => __('Disable collapsing filter form', 'directories'),
                        '#default_value' => !empty($settings['shown']),
                        '#horizontal' => true,
                        '#weight' => 11,
                        '#states' => [
                            'visible' => [
                                $show_filters_selector => ['type' => 'checked', 'value' => true],
                                $show_in_modal_selector => ['type' => 'checked', 'value' => false]
                            ],
                        ],
                    ],
                    'auto_submit' => [
                        '#title' => __('Auto submit filter form', 'directories'),
                        '#type' => 'checkbox',
                        '#default_value' => !isset($settings['auto_submit']) || $settings['auto_submit'],
                        '#horizontal' => true,
                        '#weight' => 15,
                        '#states' => [
                            'visible' => [
                                $show_filters_selector => ['type' => 'checked', 'value' => true],
                                $show_in_modal_selector => ['type' => 'checked', 'value' => false]
                            ],
                        ],
                    ],
                ];

                $displays = AddDisplay::existingDisplays($application, $bundle->name,'default', 'filters');
                if (count($displays) > 1) {
                    $ret['display'] = [
                        '#type' => 'select',
                        '#title' => __('Select filter group', 'directories'),
                        '#options' => $displays,
                        '#horizontal' => true,
                        '#default_value' => isset($settings['display']) && isset($displays[$settings['display']]) ? $settings['display'] : null,
                        '#weight' => 7,
                        '#states' => [
                            'visible' => [
                                $show_filters_selector => ['type' => 'checked', 'value' => true],
                            ],
                        ],
                    ];
                } else {
                    $ret['display'] = [
                        '#type' => 'hidden',
                        '#default_value' => 'default',
                    ];
                }

                if (empty($bundle->info['parent'])) {
                    $ret['show_modal'] = [
                        '#type' => 'checkbox',
                        '#title' => __('Show filter form in modal window', 'directories'),
                        '#default_value' => !empty($settings['show_modal']),
                        '#horizontal' => true,
                        '#weight' => 10,
                        '#states' => [
                            'visible' => [
                                $show_filters_selector => ['type' => 'checked', 'value' => true],
                            ],
                        ],
                    ];
                }

                return $ret;

            case 'query':
                $fields = $application->Entity_Field($bundle);
                $form = array(
                    '#element_validate' => array(array($this, '_validateQuery')),
                    'fields' => array(
                        '#title' => __('Query by field', 'directories'),
                        '#horizontal' => true,
                        '#weight' => 5,
                    ),
                    'limit' => array(
                        '#type' => 'number',
                        '#title' => __('Max number of items to query', 'directories'),
                        '#description' => __('Enter 0 for not limit.', 'directories'),
                        '#default_value' => empty($settings['limit']) ? 0 : (int)$settings['limit'],
                        '#horizontal' => true,
                        '#integer' => true,
                        '#weight' => 10,
                    )
                );
                if (isset($submitValues['fields'])) {
                    // coming from form submission
                    // need to check request values since fields may have been added/removed
                    $queries = empty($submitValues['fields']) ? array(null) : $submitValues['fields'];
                } else {
                    $queries = [];
                    if (!empty($settings['fields'])) {
                        foreach ($settings['fields'] as $field_name => $query_str) {
                            $queries[] = array('field' => $field_name, 'query' => $query_str);
                        }
                    }
                    $queries[] = null;
                }
                foreach ($queries as $i => $query) {
                    $form['fields'][$i] = array(
                        '#type' => 'field_query',
                        '#fields' => $fields,
                        '#default_value' => $query,
                    );
                }
                $form['fields']['_add'] = array(
                    '#type' => 'addmore',
                    '#next_index' => ++$i,
                );

                return $form;

            case 'other':
                $form = [
                    'num' => [
                        '#type' => 'checkbox',
                        '#title' => __('Show number of items found', 'directories'),
                        '#default_value' => !empty($settings['num']),
                        '#horizontal' => true,
                        '#weight' => 5,
                    ],
                    'not_found' => [
                        '#weight' => 20,
                        'custom' => [
                            '#type' => 'checkbox',
                            '#title' => __('Customize "Not found" text', 'directories'),
                            '#default_value' => !empty($settings['not_found']['custom']),
                            '#horizontal' => true,
                        ],
                        'html' => [
                            '#type' => 'textarea',
                            '#rows' => 3,
                            '#default_value' => isset($settings['not_found']['html']) ? $settings['not_found']['html'] : null,
                            '#horizontal' => true,
                            '#states' => [
                                'visible' => [
                                    sprintf('input[name="%s"]', $application->Form_FieldName(array_merge($parents, ['not_found', 'custom']))) => ['type' => 'checked', 'value' => true],
                                ],
                            ],
                            '#description' => sprintf(
                                __('Available tokens: %s', 'directories'),
                                implode(', ', [
                                    '%current_user_id%',
                                    '%current_user_name%',
                                    '%current_user_display_name%',
                                ])
                            ),
                        ],
                    ],
                ];

                if (empty($bundle->info['is_taxonomy'])
                    && empty($bundle->info['internal'])
                    && !empty($bundle->info['public'])
                    && empty($bundle->info['parent'])
                    && $application->isComponentLoaded('FrontendSubmit')
                ) {
                    $form['add'] = $this->addItemButton($application, $bundle, $settings, $parents);
                    $form['add']['#weight'] = 10;
                }

                return $form;
        }
    }

    public function addItemButton(Application $application, Entity\Model\Bundle $bundle, array $settings, array $parents)
    {
        return [
            'show' => [
                '#type' => 'checkbox',
                '#title' => sprintf(__('Show "%s" button', 'directories'), $bundle->getLabel('add')),
                '#default_value' => !empty($settings['add']['show']),
                '#horizontal' => true,
            ],
            'show_label' => [
                '#type' => 'checkbox',
                '#title' => sprintf(__('Show "%s" button with label', 'directories'), $bundle->getLabel('add')),
                '#default_value' => !empty($settings['add']['show_label']),
                '#horizontal' => true,
                '#states' => [
                    'visible' => [
                        sprintf('input[name="%s"]', $application->Form_FieldName(array_merge($parents, ['add', 'show']))) => ['type' => 'checked', 'value' => true],
                    ],
                ],
            ],
        ];
    }

    protected function _getSortOptions(Application $application, $bundle, $html = false)
    {
        $ret = [];
        foreach ($application->Entity_Sorts($bundle->name) as $sort_name => $sort) {
            if ($html) {
                $ret[$sort_name] = $application->H($sort['label'])
                    . '<span class="' . DRTS_BS_PREFIX . 'text-muted" style="font-style:italic;"> - ' . $application->H($sort_name) . '</span>';
            } else {
                $ret[$sort_name] = $sort['label'] . ' - ' . $sort_name;
            }
        }

        return $ret;
    }

    public function _validateFilter(Form\Form $form, &$value, $element)
    {
        if (!empty($value['show_modal'])) {
            $value['shown'] = false;
        }
    }

    public function _validateSort(Form\Form $form, &$value, $element)
    {
        if (!empty($value['default'])) {
            if (empty($value['options'])) {
                $value['options'] = [];
            }
            if (!in_array($value['default'], $value['options'])) {
                $value['options'][] = $value['default'];
            }
        }
    }

    public function _validateQuery(Form\Form $form, &$value, $element)
    {
        if (empty($value['fields'])) return;

        $queries = [];
        foreach (array_filter($value['fields']) as $query) {
            if (!strlen($query['field'])
                || !strlen(trim($query['query']))
            ) continue;

            $queries[$query['field']] = $query['query'];
        }
        $value['fields'] = $queries;
    }
}
