<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

class Gem extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'gem
                            {path:path-in-gem}
                            [{--write-to-storage}]';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';

    public $output = '';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        global $argv;
        $in = json_decode(file_get_contents(base_path("gem/forms/{$argv[2]}/spec.json")));
        $outPath = base_path("gem/forms/{$argv[2]}/build");
        $this->output = $this->ln('<div class="gem-nodes">', 1);

        foreach ($in as $node) {
            $this->output .= $this->gem($node);
        }

        $this->output .= $this->ln('</div>', 1);

        // write form
        $template = file_get_contents(base_path("gem/templates/form.blade.php"));
        $this->output = str_replace('<!-- __GENERATED_MARKUP__ -->', $this->output, $template);
        file_put_contents(base_path("gem/forms/{$argv[2]}/build/form.blade.php"), $this->output);

        // write processor
        copy(base_path("gem/templates/processor.php"), base_path("gem/forms/{$argv[2]}/build/processor.php"));

        // write summary
        copy(base_path("gem/templates/summary.php"), base_path("gem/forms/{$argv[2]}/build/summary.php"));

        // copy output to store/section
        if(in_array("--write-to-storage", $argv) !== FALSE) {
            copy(base_path("gem/forms/{$argv[2]}/build/form.blade.php"), base_path("storage/sections/{$argv[2]}/form.blade.php"));
            copy(base_path("gem/forms/{$argv[2]}/build/processor.php"), base_path("storage/sections/{$argv[2]}/processor.php"));
            copy(base_path("gem/forms/{$argv[2]}/build/summary.php"), base_path("storage/sections/{$argv[2]}/summary.php"));
        }

        echo "OK";
    }

    public function gem($_node, $_parentKey = false, $_level = 0)
    {
        $output = '';
        $key = ($_parentKey ? $_parentKey . '__' : '') . $_node->K;

        // start container
        $output .= $this->ln('<div ' .
            'class="my-3 node node-level-' . $_level . '" ' .
            'data-key="' . $key . '">', $_level + 1);

        // label
        $output .= $this->ln('<label>' . $this->formatText($_node->Q) . '</label>', $_level + 2);

        // input
        $fieldLevel = $_level + 1;
        if (!!@$_node->T) {
            switch ($_node->T) {
                case 'YNUM':
                    // start
                    $output .= $this->ln('<div class="d-flex align-items-center">', $fieldLevel + 1);

                    // YES
                    $output .= $this->ln('<label class="d-inline-flex align-items-center my-0 mr-3">', $fieldLevel + 2);
                    $output .= $this->ln('<input onchange="onGemVChange_{{ $formID }}(this)" '.
                        "{{ @\$contentData['{$key}'] === 'YES' ? 'checked' : '' }} " .
                        'name="' . $key . '" type="radio" value="YES" class="mr-1">', $fieldLevel + 3);
                    $output .= $this->ln('<span>Yes</span>', $fieldLevel + 3);
                    $output .= $this->ln('</label>', $fieldLevel + 2);

                    // NO
                    $output .= $this->ln('<label class="d-inline-flex align-items-center my-0 mr-3">', $fieldLevel + 2);
                    $output .= $this->ln('<input onchange="onGemVChange_{{ $formID }}(this)" '.
                        "{{ @\$contentData['{$key}'] === 'NO' ? 'checked' : '' }} " .
                        'name="' . $key . '" type="radio" value="NO" class="mr-1">', $fieldLevel + 3);
                    $output .= $this->ln('<span>No</span>', $fieldLevel + 3);
                    $output .= $this->ln('</label>', $fieldLevel + 2);

                    // NO
                    $output .= $this->ln('<label class="d-inline-flex align-items-center my-0 mr-3">', $fieldLevel + 2);
                    $output .= $this->ln('<input onchange="onGemVChange_{{ $formID }}(this)" '.
                        "{{ @\$contentData['{$key}'] === 'UNKNOWN' ? 'checked' : '' }} " .
                        'name="' . $key . '" type="radio" value="UNKNOWN" class="mr-1">', $fieldLevel + 3);
                    $output .= $this->ln('<span>Unknown</span>', $fieldLevel + 3);
                    $output .= $this->ln('</label>', $fieldLevel + 2);

                    // MEMO
                    $output .= $this->ln('<input onchange="onGemVChange_{{ $formID }}(this)" '.
                        'value="' . "{{ @\$contentData['{$key}_memo'] }}" . '" ' .
                        'name="' . $key . '_memo" type="text" class="form-control form-control-sm" placeholder="Memo">', $fieldLevel + 2);

                    // end
                    $output .= $this->ln('</div>', $fieldLevel + 1);
                    break;

                case 'SRV':
                    // start
                    $output .= $this->ln('<div class="d-flex align-items-center">', $fieldLevel + 1);

                    // VALUE
                    $output .= $this->ln('<input onchange="onGemVChange_{{ $formID }}(this)" '.
                        'value="' . "{{ @\$contentData['{$key}'] }}" . '" ' .
                        'name="' . $key . '" type="text" class="form-control form-control-sm" placeholder="Answer">', $fieldLevel + 2);

                    // UNKNOWN
                    $output .= $this->ln('<label class="d-inline-flex align-items-center my-0 ml-3 mr-2">', $fieldLevel + 2);
                    $output .= $this->ln('<input onchange="onGemVChange_{{ $formID }}(this)" '.
                        "{{ @\$contentData['{$key}_unknown'] ? 'checked' : '' }} " .
                        'name="' . $key . '_unknown" type="checkbox" class="mr-1">', $fieldLevel + 3);
                    $output .= $this->ln('<span>Unknown</span>', $fieldLevel + 3);
                    $output .= $this->ln('</label>', $fieldLevel + 2);

                    // MEMO
                    $output .= $this->ln('<input onchange="onGemVChange_{{ $formID }}(this)" '.
                        'value="' . "{{ @\$contentData['{$key}_memo'] }}" . '" ' .
                        'name="' . $key . '_memo" type="text" class="form-control form-control-sm" placeholder="Memo">', $fieldLevel + 2);

                    // end
                    $output .= $this->ln('</div>', $fieldLevel + 1);
                    break;

                case 'Text with Memo':
                    // start
                    $output .= $this->ln('<div class="d-flex align-items-center">', $fieldLevel + 1);

                    // VALUE
                    $output .= $this->ln('<input onchange="onGemVChange_{{ $formID }}(this)" '.
                        'value="' . "{{ @\$contentData['{$key}'] }}" . '" ' .
                        'name="' . $key . '" type="text" class="form-control form-control-sm mr-2" placeholder="Answer">', $fieldLevel + 2);

                    // MEMO
                    $output .= $this->ln('<input onchange="onGemVChange_{{ $formID }}(this)" '.
                        'value="' . "{{ @\$contentData['{$key}_memo'] }}" . '" ' .
                        'name="' . $key . '_memo" type="text" class="form-control form-control-sm" placeholder="Memo">', $fieldLevel + 2);

                    // end
                    $output .= $this->ln('</div>', $fieldLevel + 1);
                    break;

                case 'Multi Checkbox with Other':
                    // start
                    $output .= $this->ln('<div class="mt-3">', $fieldLevel + 1);

                    foreach ($_node->Options as $option) {
                        $output .= $this->ln('<label class="d-flex align-items-center mb-1 mr-2">', $fieldLevel + 2);
                        $output .= $this->ln('<input onchange="onGemVChange_{{ $formID }}(this)" '.
                            "{{ isset(\$contentData['{$key}']) && in_array('" . str_replace("'", "\\'", $option) . "', \$contentData['{$key}']) !== FALSE ? 'checked' : '' }} " .
                            'name="' . $key . '[]" value="' . $option . '" type="checkbox" class="mr-1">', $fieldLevel + 3);
                        $output .= $this->ln('<span>' . $option . '</span>', $fieldLevel + 3);
                        $output .= $this->ln('</label>', $fieldLevel + 2);
                    }

                    // OTHER
                    $output .= $this->ln('<input onchange="onGemVChange_{{ $formID }}(this)" '.
                        'value="' . "{{ @\$contentData['{$key}_other'] }}" . '" ' .
                        'name="' . $key . '_other" type="text" class="form-control form-control-sm my-3" placeholder="Other">', $fieldLevel + 2);

                    // end
                    $output .= $this->ln('</div>', $fieldLevel + 1);
                    break;

                case 'Accept':
                    // start
                    $output .= $this->ln('<div class="d-flex align-items-center">', $fieldLevel + 1);

                    // YES
                    $output .= $this->ln('<label class="d-inline-flex align-items-center my-0 mr-3">', $fieldLevel + 2);
                    $output .= $this->ln('<input onchange="onGemVChange_{{ $formID }}(this)" '.
                        "{{ @\$contentData['{$key}'] === 'ACCEPT' ? 'checked' : '' }} " .
                        'name="' . $key . '" type="radio" value="ACCEPT" class="mr-1">', $fieldLevel + 3);
                    $output .= $this->ln('<span>Accept</span>', $fieldLevel + 3);
                    $output .= $this->ln('</label>', $fieldLevel + 2);

                    // NO
                    $output .= $this->ln('<label class="d-inline-flex align-items-center my-0 mr-3">', $fieldLevel + 2);
                    $output .= $this->ln('<input onchange="onGemVChange_{{ $formID }}(this)" '.
                        "{{ @\$contentData['{$key}'] === 'REJECT' ? 'checked' : '' }} " .
                        'name="' . $key . '" type="radio" value="REJECT" class="mr-1">', $fieldLevel + 3);
                    $output .= $this->ln('<span>Reject</span>', $fieldLevel + 3);
                    $output .= $this->ln('</label>', $fieldLevel + 2);

                    // end
                    $output .= $this->ln('</div>', $fieldLevel + 1);
                    break;

                default:
                    dump("Unknown type: {$_node->T}");
                    break;
            }
        }

        // subs
        if (!!@$_node->S) {
            $output .= $this->ln('<div class="subs pl-4">', $_level + 2);
            foreach ($_node->S as $sub) {
                $output .= $this->gem($sub, $key, $_level + 2);
            }
            $output .= $this->ln('</div>', $_level + 2);
        }

        // close container
        $output .= $this->ln('</div>', $_level + 1);
        $output .= $this->nl();

        return $output;
    }

    public function formatText($_text) {
        $_text = preg_replace("/\{\{(.+?)\}\}/", '<span field="$1"></span>', $_text);
        return nl2br($_text);
    }

    public function ln($_line, $_indent = 1, $_nlAfter = true)
    {
        return str_repeat(" ", $_indent * 4) . $_line . ($_nlAfter ? "\n" : '');
    }

    public function nl()
    {
        return "\n";
    }

}
