import { Notice, PluginSettingTab, Setting } from 'obsidian'
import { MicroPluginSettingsViewModel, MicroPluginSettingsDelegate } from '@views/MicroPluginSettingsViewModel'
import { ConfigResponse } from '@networking/ConfigResponse'

/*
 * Plugin Settings View subclasses PluginSettingTab, and is presented via
 * Obsidian's Settings Window.
 *
 * The data used to populate this view and all the interaction with the
 * view is handled by the view's view model. All this view does is to call
 * methods on the view model and observe (via delegate) changes so it
 * can react properly.
 */
export class MicroPluginSettingsView extends PluginSettingTab implements MicroPluginSettingsDelegate {

    // Properties

    private viewModel: MicroPluginSettingsViewModel

    // Life cycle

    constructor(viewModel: MicroPluginSettingsViewModel) {
        super(app, viewModel.plugin)

        this.viewModel = viewModel
    }

    // Public

    public display() {
        this.viewModel.delegate = this

        if (!this.viewModel.hasAppToken) {
            this.makeLoginView()
        } else {
            this.makeSettingsView()
        }
    }

    public hide() {
        super.hide()

        this.viewModel.delegate = undefined
    }

    // MicroPluginSettingsDelegate

    public loginDidSucceed(response: ConfigResponse) {
        this.display()

        new Notice(
            'Login succeeded'
        )
    }

    public loginDidFail(error: Error) {
        this.display()

        new Notice(
            'Login failed'
        )
    }

    public logoutDidSucceed() {
        this.display()
    }

    public refreshDidFail(error: Error) {
        this.display()

        new Notice(
            'Blogs refresh failed'
        )
    }

    public refreshDidSucceed(response: ConfigResponse) {
        this.display()

        new Notice(
            'Blog(s) refreshed'
        )
    }

    // Private

    private makeLoginView() {
        const { containerEl } = this

        containerEl.empty()
        containerEl.createEl('h2', { text: 'Micropub' })

        new Setting(containerEl)
            .setName('App Token')
            .setDesc('This will be autogenerated in the future.')
            .addText(text => text
                .setPlaceholder('Enter app token')
                .setValue(this.viewModel.appToken)
                .onChange(value => {
                    this.viewModel.appToken = value
                })
            )

        new Setting(containerEl)
            .setName('Site URL')
            .setDesc('Your site\'s full address, eg. https://example.com.')
            .addText(text => text
                .setPlaceholder('https://example.com')
                .setValue(this.viewModel.siteUrl)
                .onChange(value => {
                    this.viewModel.siteUrl = value
                })
            )

        new Setting(containerEl)
            .setName('Micropub Endpoint')
            .setDesc('Your site\'s micropub endpoint.')
            .addText(text => text
                .setPlaceholder('https://example.com/micropub')
                .setValue(this.viewModel.micropubEndpoint)
                .onChange(value => {
                    this.viewModel.micropubEndpoint = value
                })
            )

        new Setting(containerEl)
            .addButton(button => button
                .setButtonText('Log in')
                .setCta()
                .onClick(async _ => {
                    button
                        .setDisabled(true)
                        .removeCta()
                        .setButtonText('Logging in...')

                    await this.viewModel.validate()
                })
            )
    }

    private makeSettingsView() {
        const { containerEl } = this

        containerEl.empty()
        containerEl.createEl('h2', { text: 'Micropub' })

        new Setting(containerEl)
            .setName('Blog')
            .setDesc('Default blog for new posts.')
            .addDropdown(dropDown => dropDown
                .addOptions(this.viewModel.blogs)
                .setValue(this.viewModel.selectedBlogID)
                .onChange(value => {
                    this.viewModel.selectedBlogID = value
                })
            )
            .addExtraButton(button => button
                .setIcon('sync')
                .setTooltip('Refresh blogs')
                .onClick(async () => {
                    button
                        .setDisabled(true)

                    await this.viewModel.refreshBlogs()
                })
            )

        new Setting(containerEl)
            .setName('Categories')
            .setDesc('Default list of categories for new posts.')
            .addText(text => text
                .setPlaceholder('category1, category2, category3')
                .setValue(this.viewModel.tags)
                .onChange(value => {
                    this.viewModel.tags = value
                })
            )

        new Setting(containerEl)
            .setName('Post visibility')
            .setDesc('Default visibility for new posts.')
            .addDropdown(dropDown => dropDown
                .addOption('draft', 'Draft')
                .addOption('published', 'Public')
                .setValue(this.viewModel.visibility)
                .onChange(value => {
                    this.viewModel.visibility = value
                })
            )

        new Setting(this.containerEl)
            .setName('Sponsor')
            .setDesc('Like this plugin? Say thanks with a coffee :-)')
            .addButton(button =>
                button.buttonEl.outerHTML = '<a href="https://ko-fi.com/Z8Z0C9KPT" target="_blank"><img height="36" style="border:0px;height:36px;" src="https://storage.ko-fi.com/cdn/kofi3.png?v=3" border="0" alt="Buy Me a Coffee at ko-fi.com" /></a>'
            )

        new Setting(containerEl)
            .addButton(button => button
                .setButtonText('Log out')
                .setCta()
                .onClick(_ => {
                    this.viewModel.logout()
                })
            )
    }
}