<template>
    <div class="a-tracklist-editor">
        <div class="flex-row">
            <div class="flex-grow-1">
                <slot name="title" />
            </div>
            <div class="flex-row align-right">
                <div class="field has-addons">
                    <p class="control">
                        <button type="button" :class="['button','p-2', page == Page.Text ? 'is-primary' : 'is-light']"
                                @click="page = Page.Text">
                            <span class="icon is-small">
                                <i class="fa fa-pencil"></i>
                            </span>
                            <span>{{ labels.text }}</span>
                        </button>
                    </p>
                    <p class="control">
                        <button type="button" :class="['button','p-2', page == Page.List ? 'is-primary' : 'is-light']"
                                @click="page = Page.List">
                            <span class="icon is-small">
                                <i class="fa fa-list"></i>
                            </span>
                            <span>{{ labels.list }}</span>
                        </button>
                    </p>
                    <p class="control ml-3">
                        <button type="button" class="button is-info square"
                            :title="labels.settings"
                            @click="$refs.settings.open()">
                            <span class="icon is-small">
                                <i class="fa fa-cog"></i>
                            </span>
                        </button>
                    </p>
                </div>
            </div>
        </div>
        <section v-show="page == Page.Text" class="panel">
            <textarea ref="textarea" class="is-fullwidth is-size-6" rows="20"
                @change="updateList"
            />

        </section>
        <section v-show="page == Page.List" class="panel">
            <a-form-set ref="formset"
                :form-data="formData" :initials="initData.items"
                :columnsOrderable="true" :labels="labels"
                order-by="position"
                @load="updateInput" @colmove="onColumnMove" @move="updateInput"
                @cell="onCellEvent">
                <template v-for="[name,slot] of rowsSlots" :key="slot"
                        v-slot:[slot]="data">
                    <slot v-if="name != 'row-tail'" :name="name" v-bind="data"/>
                </template>
            </a-form-set>
        </section>

        <a-modal ref="settings" :title="labels.settings">
            <template #default>
                <div class="field">
                    <label class="label" style="vertical-align: middle">
                        {{ labels.columns }}
                    </label>
                    <table class="table is-bordered"
                            style="vertical-align: middle">
                        <tr v-if="$refs.formset">
                            <a-row :columns="$refs.formset.rows.columnNames"
                                    :item="$refs.formset.rows.columnLabels"
                                    @move="$refs.formset.rows.moveColumn"
                                    >
                                <template v-slot:cell-after="{cell}">
                                    <td style="cursor:pointer;" v-if="cell.col < $refs.formset.rows.columns_.length-1">
                                        <span class="icon" @click="$refs.formset.rows.moveColumn({from: cell.col, to: cell.col+1})"
                                            ><i class="fa fa-left-right"/>
                                        </span>
                                    </td>
                                </template>
                            </a-row>
                        </tr>
                    </table>
                </div>

                <div class="flex-row">
                    <div class="field is-inline-block is-vcentered flex-grow-1">
                        <label class="label is-inline mr-2"
                                style="vertical-align: middle">
                            Séparateur</label>
                        <div class="control is-inline-block"
                                style="vertical-align: middle;">
                            <input type="text" ref="sep" class="input is-inline is-text-centered is-small"
                                style="max-width: 5em;"
                                v-model="separator" @change="updateList()"/>
                        </div>
                    </div>
                </div>
            </template>
            <template #footer>
                <div class="flex-row align-right">
                    <a-action-button icon="fa fa-floppy-disk"
                             v-if="settingsChanged"
                             class="button control p-2 mr-3 is-secondary" run-class="blink"
                            :url="settingsUrl" method="POST"
                            :data="settings"
                            :aria-label="labels.save_settings"
                            @done="settingsSaved()">
                        {{ labels.save_settings }}
                    </a-action-button>
                    <button class="button" type="button" @click="$refs.settings.close()">
                        Fermer
                    </button>
                </div>
            </template>
        </a-modal>
    </div>
</template>
<script>
import {dropRightWhile, cloneDeep, isEqual} from 'lodash'

import AActionButton from './AActionButton'
import AFormSet from './AFormSet'
import ARow from './ARow'
import AModal from "./AModal"

/// Page display
export const Page = {
    Text: 0, List: 1, Settings: 2,
}

export default {
    components: { AActionButton, AFormSet, ARow, AModal },
    props: {
        formData: Object,
        labels: Object,

        ///! initial data as: {items: [], fields: {column_name: label, settings: {}}
        initData: Object,
        dataPrefix: String,
        settingsUrl: String,
        defaultColumns: {
            type: Array,
            default: () => ['artist', 'title', 'tags', 'album', 'year', 'timestamp']},
    },

    data() {
        const settings = {
            // tracklist_editor_columns: this.columns,
            tracklist_editor_sep: ' -- ',
        }
        return {
            Page: Page,
            page: Page.Text,
            extraData: {},
            settings,
            savedSettings: cloneDeep(settings),
        }
    },

    computed: {
        rows() { return this.$refs.formset && this.$refs.formset.rows },
        columns() { return this.rows && this.rows.columns_ || [] },

        settingsChanged() {
            var k = Object.keys(this.savedSettings)
                          .findIndex(k => !isEqual(this.settings[k], this.savedSettings[k]))
            return k != -1
        },

        separator: {
            set(value) {
                this.settings.tracklist_editor_sep = value
                if(this.page == Page.List)
                    this.updateInput()
            },
            get() { return this.settings.tracklist_editor_sep }
        },

        rowsSlots() {
            return Object.keys(this.$slots)
                .filter(x => x.startsWith('row-') || x.startsWith('rows-') || x.startsWith('control-'))
                .map(x => [x, x.startsWith('rows-') ? x.slice(5) : x])
        },
    },

    methods: {
        onCellEvent(event) {
            switch(event.name) {
                case 'change': this.updateInput();
                               break;
            }
        },

        onColumnMove() {
            this.settings.tracklist_editor_columns = this.$refs.formset.rows.columnNames
            if(this.page == this.Page.List)
                this.updateInput()
            else
                this.updateList()
        },

        updateList() {
            const items = this.toList(this.$refs.textarea.value)
            this.$refs.formset.set.reset(items)
        },

        updateInput() {
            const input = this.toText(this.$refs.formset.items)
            this.$refs.textarea.value = input
        },

        /**
         * From input and separator, return list of items.
         */
        toList(input) {
            const columns = this.$refs.formset.rows.columns_
            var lines = input.split('\n')
            var items = []

            for(let line of lines) {
                line = line.trimLeft()
                if(!line)
                    continue

                var lineBits = line.split(this.separator)
                var item = {}
                for(var col in columns) {
                    if(col >= lineBits.length)
                        break
                    const column = columns[col]
                    item[column.name] = lineBits[col].trim()
                }
                item && items.push(item)
            }
            return items
        },

        /**
         * From items and separator return a string
         */
        toText(items) {
            const columns = this.$refs.formset.rows.columns_
            const sep = ` ${this.separator.trim()} `
            const lines = []
            for(let item of items) {
                if(!item)
                    continue
                var line = []
                for(var col of columns)
                    line.push(item.data[col.name] || '')
                line = dropRightWhile(line, x => !x || !('' + x).trim())
                line = line.join(sep).trimRight()
                lines.push(line)
            }
            return lines.join('\n')
        },


        _data_key(key) {
            key = key.slice(this.dataPrefix.length)
            try {
                var [index, attr] = key.split('-', 1)
                return [Number(index), attr]
            }
            catch(err) {
                return [null, key]
            }
        },

        //! Update saved settings from this.settings
        settingsSaved(settings=null) {
            if(settings !== null)
                this.settings = settings
            if(this.$refs.settings)
                this.$refs.settings.close()
            this.savedSettings = cloneDeep(this.settings)
        },
    },

    mounted() {
        const settings = this.initData && this.initData.settings
        if(settings) {
            this.settingsSaved(settings)
            this.rows.sortColumns(settings.tracklist_editor_columns)
        }
        this.page = this.initData.items.length ? Page.List : Page.Text
    },
}
</script>
