odoo.define('jd_base.form_widgets', function (require) {
    "use strict";
    var core = require('web.core');
    var formRelation = require("web.form_relational");
    var common = require('web.form_common');
    var formView = require('web.FormView');
    var QWeb = core.qweb;
    var _t = core._t;
    var FieldBinaryImage = core.form_widget_registry.get('image');
    var WidgetButton = core.form_tag_registry.get('button');
    var utils = require('web.utils');
    var _suppler_set_value_ = common.AbstractField.prototype.set_value;
    /**
     * 支持EAS FID作为ID用。
     * @param ids
     * @returns {*}
     */
    formRelation.AbstractManyField.prototype.set_value = function (ids) {
        ids = (ids || []).slice();
        if (_.find(ids, function (id) {
                return typeof(id) === "string";
            })) {
            //throw new Error("set_value of '"+this.name+"' must receive an list of ids without virtual ids.", ids);
        }
        if (_.find(ids, function (id) {
                return (typeof(id) !== "number") && (typeof(id) !== "string");
            })) {
            return this.send_commands(ids, {'_inhibit_on_change_flag': this._inhibit_on_change_flag});
        }
        this.dataset.reset_ids(ids);
        return $.when(_suppler_set_value_.call(this, ids));
    };

    /**
     * 使用模型中的字段，控制“编辑”按钮是否显示。
     * 把<field name="hide_edit_button" invisible="1"/>加入到视图中。
     */
    var _super_form_view_load_record = formView.prototype.load_record;
    formView.prototype.load_record = function (record) {
        var result = $.when(_super_form_view_load_record.call(this, record));
        var fields_values = this.get_fields_values();
        var self = this;
        var hideEditButton = false;
        var hasIsFormEditableField = false;
        for (var key in fields_values) {
            if (key == 'hide_edit_button') {
                hasIsFormEditableField = true;
                if (fields_values[key]) {
                    hideEditButton = true;
                }
                break;
            }
        }
        if (hideEditButton) {
            if (self.$buttons) {
                self.$buttons.find(".o_form_button_edit").hide();
            }
        } else if (hasIsFormEditableField) {
            if (self.$buttons) {
                self.$buttons.find(".o_form_button_edit").show();
            }
        }
        return result;
    };


    /**
     * 添加字段属性 force_save=1时，强制保存readonly字段。
     * @type {Function|*|FormView._process_save}
     * @private
     */
    var _supper_process_save = formView.prototype._process_save;
    formView.prototype._process_save = function (save_obj) {
        var self = this;
        var prepend_on_create = save_obj.prepend_on_create;
        var def_process_save = $.Deferred();
        try {
            var form_invalid = false,
                values = {},
                first_invalid_field = null,
                readonly_values = {},
                deferred = [];

            $.when.apply($, deferred).always(function () {

                _.each(self.fields, function (f) {
                    if (!f.is_valid()) {
                        form_invalid = true;
                        if (!first_invalid_field) {
                            first_invalid_field = f;
                        }
                    } else if (f.name !== 'id' && (!self.datarecord.id || f._dirty_flag)) {
                        // Special case 'id' field, do not save this field
                        // on 'create' : save all non readonly fields
                        // on 'edit' : save non readonly modified fields
                        var forceSave = false;
                        if (f && f.field && f.field.__attrs && f.field.__attrs.force_save) {
                            forceSave = true;
                        }
                        if (!f.get("readonly") || forceSave) {
                            values[f.name] = f.get_value(true);
                        } else {
                            readonly_values[f.name] = f.get_value(true);
                        }
                    }

                });

                // Heuristic to assign a proper sequence number for new records that
                // are added in a dataset containing other lines with existing sequence numbers
                if (!self.datarecord.id && self.fields.sequence && !_.has(values, 'sequence') && !_.isEmpty(self.dataset.cache)) {
                    // Find current max or min sequence (editable top/bottom)
                    var current = _[prepend_on_create ? "min" : "max"](
                        _.map(self.dataset.cache, function (o) {
                            return o.values.sequence
                        })
                    );
                    values['sequence'] = prepend_on_create ? current - 1 : current + 1;
                }
                if (form_invalid) {
                    self.set({'display_invalid_fields': true});
                    first_invalid_field.focus();
                    self.on_invalid();
                    def_process_save.reject();
                } else {
                    self.set({'display_invalid_fields': false});
                    var save_deferral;
                    if (!self.datarecord.id) {
                        // Creation save
                        save_deferral = self.dataset.create(values, {readonly_fields: readonly_values}).then(function (r) {
                            self.display_translation_alert(values);
                            return self.record_created(r, prepend_on_create);
                        }, null);
                    } else if (_.isEmpty(values)) {
                        // Not dirty, noop save
                        save_deferral = $.Deferred().resolve({}).promise();
                    } else {
                        // Write save
                        save_deferral = self.dataset.write(self.datarecord.id, values, {readonly_fields: readonly_values}).then(function (r) {
                            self.display_translation_alert(values);
                            return self.record_saved(r);
                        }, null);
                    }
                    save_deferral.then(function (result) {
                        def_process_save.resolve(result);
                    }).fail(function () {
                        def_process_save.reject();
                    });
                }
            });
        } catch (e) {
            console.error(e);
            return def_process_save.reject();
        }
        return def_process_save;
    }

    /**
     * 阿里OSS控件
     */
    var AliOssImage = FieldBinaryImage.extend({

        is_base64_value: function (value) {
            var p = /^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$/;
            return (p).test(value);
        },

        render_value: function () {
            var self = this;
            var value = this.get('value');
            var url = this.placeholder;
            if (value && self.is_base64_value(value)) {
                url = 'data:image/png;base64,' + value;
            } else if (value) {
                url = value;
            }
            //if (!url) {
            //    url = this.placeholder;
            //}
            //url = "//food-images.jdg.com.cn/2017/05/10/28924838-6fcd-4b55-ae54-ab854f18c1c5.png";
            var $img = $(QWeb.render("FieldBinaryImage-img", {widget: this, url: url}));
            var self = this;
            $img.click(function (e) {
                if (self.view.get("actual_mode") == "view") {
                    var $button = $(".o_form_button_edit");
                    $button.openerpBounce();
                    e.stopPropagation();
                }
            });
            this.$('> img').remove();
            if (self.options.size) {
                $img.css("width", "" + self.options.size[0] + "px");
                $img.css("height", "" + self.options.size[1] + "px");
            }
            this.$el.prepend($img);
            $img.on('error', function () {
                self.on_clear();
                $img.attr('src', self.placeholder);
                self.do_warn(_t("Image"), _t("Could not display the selected image."));
            });
        }

    });

    /**
     *
     */
    var JdgWidgetButton = WidgetButton.extend({
        on_confirmed: function () {
            var self = this;
            var context = this.build_context();
            var cannot_edit = this.node.attrs.cannot_edit;
            if (cannot_edit === '1') {
                this.view.to_view_mode();
            }
            return this.view.do_execute_action(
                _.extend({}, this.node.attrs, {context: context}),
                this.view.dataset, this.view.datarecord.id, function (reason) {
                    if (!_.isObject(reason)) {
                        self.view.recursive_reload();
                    }
                }).fail(function () {
                self.view.recursive_reload();
            });
        },
    });

    core.form_widget_registry.add('alioss_image', AliOssImage);
    core.form_tag_registry.add('button', JdgWidgetButton)
});