<?php

namespace App\Support;

use Illuminate\Support\HtmlString;
use Illuminate\Support\Str;

class FormHelper
{
    protected function attributes(array $attributes = []): string
    {
        $compiled = [];

        foreach ($attributes as $key => $value) {
            if ($value === null || $value === false) {
                continue;
            }

            if ($value === true) {
                $compiled[] = $key . '="' . $key . '"';
                continue;
            }

            $compiled[] = $key . '="' . e((string) $value, false) . '"';
        }

        return $compiled ? ' ' . implode(' ', $compiled) : '';
    }

    protected function isSelected($value, $selected): bool
    {
        if (is_array($selected)) {
            return in_array($value, $selected, true);
        }

        return (string) $value === (string) $selected;
    }

    public function open(array $attributes = []): HtmlString
    {
        $method = strtoupper($attributes['method'] ?? 'POST');
        $action = $attributes['url'] ?? url('/');
        $attributes = array_diff_key($attributes, array_flip(['url', 'method']));

        $attributes['method'] = $method;
        $attributes['action'] = $action;

        if (! isset($attributes['accept-charset'])) {
            $attributes['accept-charset'] = 'UTF-8';
        }

        if ($method !== 'GET' && $method !== 'POST') {
            $attributes['_method'] = $method;
            $attributes['method'] = 'POST';
        }

        $html = '<form' . $this->attributes($attributes) . '>';

        if (($method !== 'GET' && $method !== 'POST')) {
            $html .= method_field($method);
        }

        if ($method === 'POST') {
            $html .= csrf_field();
        }

        return new HtmlString($html);
    }

    public function close(): HtmlString
    {
        return new HtmlString('</form>');
    }

    public function text($name, $value = null, array $attributes = []): HtmlString
    {
        $attributes['type'] = 'text';
        $attributes['name'] = $name;
        $attributes['value'] = $value;

        return new HtmlString('<input' . $this->attributes($attributes) . '>');
    }

    public function password($name, array $attributes = []): HtmlString
    {
        $attributes['type'] = 'password';
        $attributes['name'] = $name;

        return new HtmlString('<input' . $this->attributes($attributes) . '>');
    }

    public function file($name, array $attributes = []): HtmlString
    {
        $attributes['type'] = 'file';
        $attributes['name'] = $name;

        return new HtmlString('<input' . $this->attributes($attributes) . '>');
    }

    public function hidden($name, $value = null, array $attributes = []): HtmlString
    {
        $attributes['type'] = 'hidden';
        $attributes['name'] = $name;
        $attributes['value'] = $value;

        return new HtmlString('<input' . $this->attributes($attributes) . '>');
    }

    public function textarea($name, $value = null, array $attributes = []): HtmlString
    {
        $attributes['name'] = $name;

        $html = '<textarea' . $this->attributes($attributes) . '>' . e((string) $value, false) . '</textarea>';

        return new HtmlString($html);
    }

    public function checkbox($name, $value = 1, $checked = false, array $attributes = []): HtmlString
    {
        $attributes['type'] = 'checkbox';
        $attributes['name'] = $name;
        $attributes['value'] = $value;

        if ($checked) {
            $attributes['checked'] = 'checked';
        }

        return new HtmlString('<input' . $this->attributes($attributes) . '>');
    }

    public function select($name, $options = [], $selected = null, array $attributes = []): HtmlString
    {
        $attributes['name'] = $name;
        $html = '<select' . $this->attributes($attributes) . '>';

        foreach ($options as $optionValue => $optionLabel) {
            $optionAttributes = ['value' => $optionValue];
            if ($this->isSelected($optionValue, $selected)) {
                $optionAttributes['selected'] = 'selected';
            }
            $html .= '<option' . $this->attributes($optionAttributes) . '>' . e((string) $optionLabel, false) . '</option>';
        }

        $html .= '</select>';

        return new HtmlString($html);
    }

    public function selectRange($name, $begin, $end, $selected = null, array $attributes = []): HtmlString
    {
        $options = [];
        for ($i = $begin; $i <= $end; $i++) {
            $options[$i] = $i;
        }

        return $this->select($name, $options, $selected, $attributes);
    }

    public function date($name, $value = null, array $attributes = []): HtmlString
    {
        $attributes['type'] = 'date';
        $attributes['name'] = $name;
        $attributes['value'] = $value;

        return new HtmlString('<input' . $this->attributes($attributes) . '>');
    }
}
