function AdminWriteEditForm(opts) {
    bindEvents(this);
    opts = opts || {};

    this.opts = opts;
    this.form = document.forms[this.isPage() ? 'pageForm' : 'postForm'];
    this.previewTimeout = null;
    this.previewRequest = null;
    this.firstPreviewShowDone = false;
    this.tocByLang = {};

    if (!this.isEditing() && this.isPost()) {
        for (var i = 0; i < opts.langs.length; i++) {
            this.tocByLang[opts.langs[i]] = false;
        }
    }

    this.form.addEventListener('submit', this.onSubmit);
    this.form.title.addEventListener('input', this.onInput);
    this.form.text.addEventListener('input', this.onInput);
    if (this.isPost())
        this.form.keywords.addEventListener('input', this.onInput);

    ge('toggle_wrap').addEventListener('click', this.onToggleWrapClick);

    if (this.isPost())
        ge('toc_cb').addEventListener('change', this.onToCCheckboxChange);
    else if (this.isPage() && this.isEditing())
        ge('render_title_cb').addEventListener('change', this.onRenderTitleCheckboxChange);

    var lang = 'en';
    if (this.isPost()) {
        lang = this.getCurrentLang();
        this.form.lang.addEventListener('change', this.onLangChanged);
    }

    var draftId, draftType = !this.isPost() ? 'page' : 'post';
    if (this.isEditing()) {
        draftId = 'edit_'+draftType+this.opts.id;
    } else {
        draftId = 'new_'+draftType;
    }

    this.draft = new Draft(draftId, lang);
    if (this.isEditing()) {
        if (this.isPost()) {
            for (var l in opts.texts) {
                this.draft.setLang(l)
                this.draft.setTitle(opts.texts[l].title)
                this.draft.setText(opts.texts[l].md)
                this.draft.setKeywords(opts.texts[l].keywords)
                this.tocByLang[l] = opts.texts[l].toc
            }
            this.draft.setLang(lang)
        } else {
            this.draft.setTitle(opts.text.title)
            this.draft.setText(opts.text.text)
        }
        this.showPreview()
    } else {
        this.fillFromDraft()
    }
}

extend(AdminWriteEditForm.prototype, {
    getCurrentLang: function () {
        return this.form.lang.options[this.form.lang.selectedIndex].value;
    },
    isPost: function() { return !this.opts.pages },
    isPage: function() { return !!this.opts.pages },
    isEditing: function() { return !!this.opts.edit },

    fillFromDraft: function(opts) {
        opts = opts || {applyEventEmpty: false};
        var whats = ['title', 'text'];
        if (this.isPost())
            whats.push('keywords');
        for (var i = 0; i < whats.length; i++) {
            var what = whats[i];
            if (this.draft.get(what) !== '' || opts.applyEvenEmpty)
                this.form[what].value = this.draft.get(what);
        }
        if (this.form.text.value !== '' || opts.applyEvenEmpty)
            this.showPreview();
    },

    callShowPreview: function() {
        if (this.previewTimeout !== null)
            clearTimeout(this.previewTimeout);

        this.previewTimeout = setTimeout(function() {
            this.previewTimeout = null;
            this.showPreview();
        }.bind(this), 300);
    },

    showPreview: function() {
        if (this.previewRequest !== null)
            this.previewRequest.abort();
        var params = {
            md: this.form.elements.text.value,
            use_image_previews: this.isPage() ? 1 : 0
        };
        if (this.isPost()) {
            params.title = this.form.elements.title.value;
            params.lang = this.getCurrentLang();
        }
        if (this.isPage() && this.isEditing() && this.form.render_title.checked) {
            params.title = this.form.elements.title.value;
            params.is_page = 1
        }
        this.previewRequest = ajax.post('/admin/markdown-preview.ajax', params, function(err, response) {
            if (err)
                return console.error(err);
            ge('preview_html').innerHTML = response.html;
            if (!this.firstPreviewShowDone && this.isEditing() && this.isPost()) {
                window.requestAnimationFrame(function() {
                    var taHeight = this.form.text.getBoundingClientRect().height;
                    var blogPostHeight = ge('blog_post').getBoundingClientRect().height - 70;
                    if (blogPostHeight > taHeight) {
                        setStyle(this.form.text, {height: blogPostHeight + 'px'});
                    }
                }.bind(this))
                this.firstPreviewShowDone = true;
            }
        }.bind(this));
    },

    showError: function(code, message) {
        if (code) {
            var el = ge('form-error')
            var label = escape(lang('err_blog_'+code))
            if (message)
                label += ' (' + message + ')'
            el.innerHTML = label
            el.style.display = 'block'
        } else if (message) {
            alert(lang('error')+': '+message)
        }
    },

    hideError: function() {
        var el = ge('form-error')
        el.style.display = 'none'
    },

    onSubmit: function(evt) {
        var fields = []
        try {
            if (this.isEditing()) {
                fields.push('new_short_name');
            } else {
                fields.push('short_name');
            }
            fields.forEach(function(field) {
                if (evt.target.elements[field].value.trim() === '')
                    throw 'no_'+field
            })

            var fd = new FormData();
            fields.forEach(function(f) {
                console.log('field: ' + f)
                fd.append(f, evt.target[f].value.trim());
            })

            // fd.append('lang', this.getCurrentLang())
            if (this.isPost() || this.isEditing())
                fd.append('visible', ge('visible_cb').checked ? 1 : 0);
            if (this.isPage() && this.isEditing()) {
                fd.append('render_title', ge('render_title_cb').checked ? 1 : 0);
                fd.append('parent', evt.target.elements.parent.value.trim());
            }

            // text-specific fields
            var atLeastOneLangIsWritten = false;
            var writtenLangs = [];
            if (this.isPost()) {
                fd.append('source_url', evt.target.source_url.value);
                this.opts.langs.forEach(function(l) {
                    var title = this.draft.getForLang(l, 'title');
                    var text = this.draft.getForLang(l, 'text');
                    var keywords = this.draft.getForLang(l, 'keywords');
                    if (title !== '' && text !== '') {
                        atLeastOneLangIsWritten = true;
                        fd.append('title:' + l, title);
                        fd.append('text:' + l, text);
                        fd.append('keywords:' + l, keywords);
                        fd.append('toc:' + l, this.tocByLang[l] ? 1 : 0);
                        writtenLangs.push(l);
                    }
                }.bind(this))
            } else {
                var title = this.draft.getTitle()
                var text = this.draft.getText()
                if (title !== '' && text !== '') {
                    atLeastOneLangIsWritten = true;
                    fd.append('title', title);
                    fd.append('text', text);
                }
            }

            if (!atLeastOneLangIsWritten)
                throw 'no_text'

            fd.append('langs', writtenLangs.join(','));

            // date field
            if (this.isPost()) {
                var dateInput = evt.target.elements.date;
                if (!dateInput.value)
                    throw 'no_date'
                fd.append('date', dateInput.value);
            }

            fd.append('token', this.opts.token);
            cancelEvent(evt);

            this.hideError();

            ajax.post(evt.target.action, fd, function(error, response) {
                if (error) {
                    this.showError(error.code, error.message);
                    return;
                }

                if (response.url) {
                    this.draft.reset(this.opts.langs);
                    window.location = response.url;
                }
            }.bind(this));
        } catch (e) {
            var errorText = typeof e == 'string' ? lang('error')+': '+lang((this.isPage() ? 'err_pages_' : 'err_blog_')+e) : e.message;
            alert(errorText);
            console.error(e);
            return cancelEvent(evt);
        }
    },

    onToggleWrapClick: function(e) {
        var textarea = this.form.elements.text
        if (!hasClass(textarea, 'nowrap')) {
            addClass(textarea, 'nowrap');
        } else {
            removeClass(textarea, 'nowrap');
        }
        return cancelEvent(e);
    },

    onInput: function(e) {
        var what = e.target.name;
        this.draft.set(what, e.target.value);

        this.callShowPreview();
    },

    onLangChanged: function(e) {
        var newLang = e.target.options[e.target.selectedIndex].value;
        this.draft.setLang(newLang);
        this.fillFromDraft({applyEvenEmpty: true});
        ge('toc_cb').checked = this.tocByLang[newLang];
    },

    onToCCheckboxChange: function(e) {
        this.tocByLang[this.getCurrentLang()] = e.target.checked;
    },

    onRenderTitleCheckboxChange: function(e) {
        this.callShowPreview();
    }
})
