"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var react_1 = tslib_1.__importDefault(require("react"));
var Item_1 = require("./Item");
var classnames_1 = tslib_1.__importDefault(require("classnames"));
var react_cropper_1 = tslib_1.__importDefault(require("react-cropper"));
var react_dropzone_1 = tslib_1.__importDefault(require("react-dropzone"));
require("blueimp-canvastoblob");
// @require 'cropperjs/dist/cropper.css';
// jest 不能支持这种写法
// import 'cropperjs/dist/cropper.css';
var find = require("lodash/find");
var qs_1 = tslib_1.__importDefault(require("qs"));
var tpl_1 = require("../../utils/tpl");
var components_1 = require("../../components");
;
;
var ImageControl = /** @class */ (function (_super) {
    tslib_1.__extends(ImageControl, _super);
    function ImageControl(props) {
        var _this = _super.call(this, props) || this;
        _this.state = {
            uploading: false,
            locked: false,
            compress: false,
            files: [],
            compressOptions: {}
        };
        _this.current = null;
        var value = props.value;
        var multiple = props.multiple;
        var joinValues = props.joinValues;
        var delimiter = props.delimiter;
        var files = [];
        if (value) {
            // files = (multiple && Array.isArray(value) ? value : joinValues ? (value as string).split(delimiter) : [value])
            files = (Array.isArray(value) ? value : (joinValues && typeof value === 'string' && multiple) ? value.split(delimiter) : [value])
                .map(function (item) { return ImageControl.valueToFile(item); })
                .filter(function (item) { return item; });
        }
        _this.state = tslib_1.__assign({}, _this.state, { files: files, crop: _this.buildCrop(props), compress: !!props.compress, compressOptions: props.compressOptions });
        _this.sendFile = _this.sendFile.bind(_this);
        _this.removeFile = _this.removeFile.bind(_this);
        _this.handleDrop = _this.handleDrop.bind(_this);
        _this.handleClick = _this.handleClick.bind(_this);
        _this.handleClick = _this.handleClick.bind(_this);
        _this.handleCrop = _this.handleCrop.bind(_this);
        _this.handleDropRejected = _this.handleDropRejected.bind(_this);
        _this.cancelCrop = _this.cancelCrop.bind(_this);
        _this.handleImageLoaded = _this.handleImageLoaded.bind(_this);
        _this.startUpload = _this.startUpload.bind(_this);
        _this.stopUpload = _this.stopUpload.bind(_this);
        _this.toggleUpload = _this.toggleUpload.bind(_this);
        _this.tick = _this.tick.bind(_this);
        _this.onChange = _this.onChange.bind(_this);
        _this.addFiles = _this.addFiles.bind(_this);
        _this.handleSelect = _this.handleSelect.bind(_this);
        _this.handlePaste = _this.handlePaste.bind(_this);
        return _this;
    }
    ImageControl.formatFileSize = function (size, units) {
        if (units === void 0) { units = [' B', ' KB', ' M', ' G']; }
        size = parseInt(size, 10) || 0;
        while (size > 1024 && units.length > 1) {
            size /= 1024;
            units.shift();
        }
        return size.toFixed(2) + units[0];
    };
    ImageControl.valueToFile = function (value, props) {
        return value ? tslib_1.__assign({}, (typeof value === 'string' ? {
            value: value,
            url: value
        } : value), { state: 'init' }) : undefined;
    };
    ImageControl.sizeInfo = function (width, height) {
        if (!width) {
            return "\u9AD8\u5EA6" + height + "px";
        }
        else if (!height) {
            return "\u5BBD\u5EA6" + width + "px";
        }
        return "\u5C3A\u5BF8\uFF08" + width + " x " + height + "\uFF09";
    };
    ImageControl.prototype.componentWillReceiveProps = function (nextProps) {
        var _this = this;
        var props = this.props;
        if (props.value !== nextProps.value) {
            var value = nextProps.value;
            var multiple = nextProps.multiple;
            var joinValues = nextProps.joinValues;
            var delimiter = nextProps.delimiter;
            var files = [];
            if (value) {
                files = (Array.isArray(value) ? value : (joinValues && typeof value === 'string') ? value.split(delimiter) : [value])
                    .map(function (item) {
                    var obj = ImageControl.valueToFile(item, nextProps);
                    var org;
                    if (obj && (org = find(_this.state.files, function (item) { return item.value === obj.value; }))) {
                        obj = tslib_1.__assign({}, org, obj);
                    }
                    return obj;
                })
                    .filter(function (item) { return item; });
            }
            this.setState({
                files: files
            });
        }
        if (props.crop !== nextProps.crop) {
            this.setState({
                crop: this.buildCrop(nextProps)
            });
        }
    };
    ImageControl.prototype.buildCrop = function (props) {
        var crop = props.crop;
        if (crop && props.multiple) {
            props.env && props.env.alert && props.env.alert('图片多选配置和裁剪配置冲突，目前不能二者都支持！');
            return null;
        }
        if (crop === true) {
            crop = {};
        }
        if (crop) {
            crop = tslib_1.__assign({ aspectRatio: 1, guides: true, dragMode: 'move', viewMode: 1, rotatable: false, scalable: false }, crop);
        }
        return crop;
    };
    ImageControl.prototype.handleDropRejected = function (rejectedFiles, evt) {
        evt.type === 'change' && alert('您选择的文件类型不符已被过滤！');
    };
    ImageControl.prototype.startUpload = function () {
        if (this.state.uploading) {
            return;
        }
        this.setState({
            uploading: true,
            locked: true,
            files: this.state.files.map(function (file) {
                if (file.state === 'error') {
                    file.state = 'pending';
                }
                return file;
            })
        }, this.tick);
    };
    ImageControl.prototype.toggleUpload = function () {
        return this.state.uploading ? this.stopUpload() : this.startUpload();
    };
    ImageControl.prototype.stopUpload = function () {
        if (!this.state.uploading) {
            return;
        }
        this.setState({
            uploading: false
        });
    };
    ImageControl.prototype.tick = function () {
        var _this = this;
        if (this.current || !this.state.uploading) {
            return;
        }
        var file = find(this.state.files, function (item) { return item.state === 'pending'; });
        if (file) {
            this.current = file;
            file.state = 'uploading';
            this.setState({
                files: this.state.files.concat()
            }, function () { return _this.sendFile(file, function (error, file, obj) {
                var files = _this.state.files.concat();
                var idx = files.indexOf(file);
                if (!~idx) {
                    return;
                }
                var newFile = file;
                if (error) {
                    newFile.state = file.state !== 'uploading' ? file.state : 'error';
                    newFile.error = error;
                    if (!_this.props.multiple && newFile.state === 'invalid') {
                        files.splice(idx, 1);
                        _this.current = null;
                        return _this.setState({
                            files: files,
                            error: error
                        }, _this.tick);
                    }
                }
                else {
                    newFile = obj;
                }
                files.splice(idx, 1, newFile);
                _this.current = null;
                _this.setState({
                    files: files
                }, _this.tick);
            }); });
        }
        else {
            this.setState({
                uploading: false,
                locked: false
            }, function () {
                _this.onChange();
                if (_this.resolve) {
                    _this.resolve(_this.state.files.some(function (file) { return file.state === 'error'; }) ? '文件上传失败请重试' : null);
                    _this.resolve = undefined;
                }
            });
        }
    };
    ImageControl.prototype.removeFile = function (file, index) {
        var files = this.state.files.concat();
        files.splice(index, 1);
        this.setState({
            files: files
        }, this.onChange);
    };
    ImageControl.prototype.editImage = function (index) {
        var multiple = this.props.multiple;
        var files = this.state.files;
        this.setState({
            cropFile: {
                preview: files[index].url,
                state: 'init'
            }
        });
    };
    ImageControl.prototype.onChange = function () {
        var _a = this.props, multiple = _a.multiple, onChange = _a.onChange, joinValues = _a.joinValues, extractValue = _a.extractValue, delimiter = _a.delimiter, valueField = _a.valueField;
        var files = this.state.files.filter(function (file) { return file.state == 'uploaded' || file.state == 'init'; });
        var newValue = files.length ? joinValues ? files[0].value : files[0] : '';
        if (multiple) {
            newValue = joinValues ? files.map(function (item) { return item.value; }).join(delimiter) : extractValue ? files.map(function (item) { return item.value; }) : files;
        }
        else {
            newValue = joinValues ? newValue.value || newValue : extractValue ? newValue[valueField || 'value'] : newValue;
        }
        onChange(newValue);
    };
    ImageControl.prototype.handleSelect = function () {
        this.refs.dropzone && this.refs.dropzone.open();
    };
    ImageControl.prototype.handleDrop = function (files) {
        var _a = this.props, multiple = _a.multiple, crop = _a.crop;
        if (crop && !multiple) {
            return this.setState({
                locked: true,
                lockedReason: '请选择放弃或者应用',
                cropFile: files[0]
            });
        }
        this.addFiles(files);
    };
    ImageControl.prototype.handlePaste = function (e) {
        var event = e.nativeEvent;
        var files = [];
        var items = event.clipboardData.items;
        [].slice.call(items).forEach(function (item) {
            var blob;
            if (item.kind !== 'file' || !(blob = item.getAsFile()) || !/^image/i.test(blob.type)) {
                return;
            }
            blob.preview = window.URL.createObjectURL(blob);
            files.push(blob);
        });
        this.handleDrop(files);
    };
    ImageControl.prototype.handleCrop = function () {
        var _this = this;
        this.refs.cropper.getCroppedCanvas().toBlob(function (file) {
            _this.addFiles([file]);
            _this.setState({
                cropFile: undefined,
                locked: false,
                lockedReason: ''
            });
        });
    };
    ImageControl.prototype.cancelCrop = function () {
        this.setState({
            cropFile: undefined,
            locked: false,
            lockedReason: ''
        }, this.onChange);
    };
    ImageControl.prototype.addFiles = function (files) {
        var _this = this;
        if (!files.length) {
            return;
        }
        var _a = this.props, multiple = _a.multiple, maxLength = _a.maxLength, maxSize = _a.maxSize, accept = _a.accept;
        var currentFiles = this.state.files;
        if (!multiple && currentFiles.length) {
            currentFiles = [];
        }
        var allowed = (multiple ? maxLength ? maxLength : (files.length + currentFiles.length) : 1) - currentFiles.length;
        var inputFiles = [];
        [].slice.call(files, 0, allowed).forEach(function (file) {
            if (maxSize && file.size > maxSize) {
                alert("\u60A8\u9009\u62E9\u7684\u6587\u4EF6 " + file.name + " \u5927\u5C0F\u4E3A " + ImageControl.formatFileSize(file.size) + " \u8D85\u51FA\u4E86\u6700\u5927\u4E3A " + ImageControl.formatFileSize(maxSize) + " \u7684\u9650\u5236\uFF0C\u8BF7\u91CD\u65B0\u9009\u62E9");
                return;
            }
            file.state = 'pending';
            if (!file.preview || !file.url) {
                file.preview = window.URL.createObjectURL(file);
            }
            inputFiles.push(file);
        });
        if (!inputFiles.length) {
            return;
        }
        this.setState({
            error: undefined,
            files: currentFiles.concat(inputFiles),
            locked: true
        }, function () {
            var autoUpload = _this.props.autoUpload;
            if (autoUpload) {
                _this.startUpload();
            }
        });
    };
    ImageControl.prototype.sendFile = function (file, cb) {
        var _this = this;
        var limit = this.props.limit;
        if (!limit) {
            return this._upload(file, cb);
        }
        var image = new Image();
        image.onload = function () {
            var width = image.width;
            var height = image.height;
            var error = '';
            if (limit.width && limit.width != width || limit.height && limit.height != height) {
                error = "\u60A8\u9009\u62E9\u7684\u56FE\u7247\u4E0D\u7B26\u5408\u5C3A\u5BF8\u8981\u6C42, \u8BF7\u4E0A\u4F20" + ImageControl.sizeInfo(limit.width, limit.height) + "\u7684\u56FE\u7247";
            }
            else if (limit.maxWidth && limit.maxWidth < width || limit.maxHeight && limit.maxHeight < height) {
                error = "\u60A8\u9009\u62E9\u7684\u56FE\u7247\u4E0D\u7B26\u5408\u5C3A\u5BF8\u8981\u6C42, \u8BF7\u4E0A\u4F20\u4E0D\u8981\u8D85\u8FC7" + ImageControl.sizeInfo(limit.maxWidth, limit.maxHeight) + "\u7684\u56FE\u7247";
            }
            else if (limit.minWidth && limit.minWidth > width || limit.minHeight && limit.minHeight > height) {
                error = "\u60A8\u9009\u62E9\u7684\u56FE\u7247\u4E0D\u7B26\u5408\u5C3A\u5BF8\u8981\u6C42, \u8BF7\u4E0A\u4F20\u4E0D\u8981\u5C0F\u4E8E" + ImageControl.sizeInfo(limit.minWidth, limit.minHeight) + "\u7684\u56FE\u7247";
            }
            else if (limit.aspectRatio && Math.abs((width / height) - limit.aspectRatio) > 0.01) {
                error = "\u60A8\u9009\u62E9\u7684\u56FE\u7247\u4E0D\u7B26\u5408\u5C3A\u5BF8\u8981\u6C42, \u8BF7\u4E0A\u4F20\u5C3A\u5BF8\u6BD4\u7387\u4E3A " + (limit.aspectRatioLabel || limit.aspectRatio) + " \u7684\u56FE\u7247";
            }
            if (error) {
                file.state = 'invalid';
                cb(error, file);
            }
            else {
                _this._upload(file, cb);
            }
        };
        image.src = (file.preview || file.url);
    };
    ImageControl.prototype._upload = function (file, cb) {
        var compressOptions = this.state.compressOptions;
        if (this.props.showCompressOptions) {
            compressOptions = tslib_1.__assign({ maxWidth: 800, maxHeight: 600 }, compressOptions);
        }
        this._send(file, this.props.reciever, { compress: this.state.compress, compressOptions: compressOptions })
            .then(function (ret) {
            if (ret.status) {
                throw new Error(ret.msg || '上传失败, 请重试');
            }
            var obj = tslib_1.__assign({}, ret.data, { state: 'uploaded' });
            obj.value = obj.value || obj.url;
            cb(null, file, obj);
        })
            .catch(function (error) { return cb(error.message || '上传失败，请重试', file); });
    };
    ImageControl.prototype._send = function (file, reciever, params) {
        var fd = new FormData();
        var data = this.props.data;
        reciever = tpl_1.filter(reciever, data);
        var fileField = this.props.fileField || 'file';
        if (/^\/api\/(?:page\/)?proxy/.test(reciever)) {
            fd.append('file', file, file.name);
            fd.append('fieldName', fileField);
        }
        else {
            fd.append(fileField, file, file.name);
        }
        var idx = reciever.indexOf('?');
        if (~idx && params) {
            params = tslib_1.__assign({}, qs_1.default.parse(reciever.substring(idx + 1)), params);
            reciever = reciever.substring(0, idx) + '?' + qs_1.default.stringify(params);
        }
        else if (params) {
            reciever += '?' + qs_1.default.stringify(params);
        }
        // params && Object.keys(params).forEach(key => {
        //     const value = (params as any)[key];
        //     fd.append(key, value);
        // });
        var env = this.props.env;
        if (!env || !env.fetcher) {
            throw new Error('fetcher is required');
        }
        return env.fetcher(reciever, fd, {
            method: 'post'
        });
    };
    ImageControl.prototype.handleClick = function () {
        this.refs.dropzone.open();
    };
    ImageControl.prototype.handleImageLoaded = function (index, e) {
        var _this = this;
        var imgDom = e.currentTarget;
        var img = new Image();
        img.onload = function () {
            delete img.onload;
            var files = _this.state.files.concat();
            var file = files[index];
            if (!file) {
                return;
            }
            file.info = tslib_1.__assign({}, file.info, { width: img.width, height: img.height });
            files.splice(index, 1, file);
            _this.setState({
                files: files
            }, file.state == 'uploaded' || file.state == 'init' ? _this.onChange : undefined);
        };
        img.src = imgDom.src;
    };
    ImageControl.prototype.validate = function () {
        var _this = this;
        if (this.state.locked && this.state.lockedReason) {
            return this.state.lockedReason;
        }
        else if (this.state.uploading || this.state.files.some(function (item) { return item.state === 'pending'; })) {
            return new Promise(function (resolve) {
                _this.resolve = resolve;
                _this.startUpload();
            });
        }
        else if (this.state.files.some(function (item) { return item.state === 'error'; })) {
            return '文件上传失败请重试';
        }
    };
    ImageControl.prototype.renderCompressOptions = function () {
        var _this = this;
        var showCompressOptions = this.props.showCompressOptions;
        var cx = this.props.classnames;
        var classPrefix = this.props.classPrefix;
        if (!showCompressOptions) {
            return;
        }
        return (react_1.default.createElement("div", { key: "options", className: "m-t" },
            react_1.default.createElement(components_1.Switch, { classPrefix: classPrefix, checked: !!this.state.compress, onChange: function (checked) { return _this.setState({ compress: checked }); }, disabled: this.props.disabled }),
            react_1.default.createElement("span", { className: "m-l-xs" }, "\u5F00\u542F\u7F29\u653E?"),
            this.state.compress && (react_1.default.createElement("div", { className: "inline" },
                react_1.default.createElement("input", { className: "form-control w-xs inline m-l-xs m-r-xs", type: "text", value: typeof this.state.compressOptions.maxWidth === 'undefined' ? 800 : this.state.compressOptions.maxWidth, onChange: function (e) { return _this.setState({ compressOptions: tslib_1.__assign({}, _this.state.compressOptions, { maxWidth: parseInt(e.currentTarget.value, 10) || 0 }) }); }, disabled: this.props.disabled }),
                react_1.default.createElement("span", { className: " m-l-xs m-r-xs" }, "X"),
                react_1.default.createElement("input", { className: "form-control w-xs inline  m-l-xs m-r-xs", type: "text", value: typeof this.state.compressOptions.maxHeight === 'undefined' ? 600 : this.state.compressOptions.maxHeight, onChange: function (e) { return _this.setState({ compressOptions: tslib_1.__assign({}, _this.state.compressOptions, { maxHeight: parseInt(e.currentTarget.value, 10) || 0 }) }); }, disabled: this.props.disabled })))));
    };
    ImageControl.prototype.render = function () {
        var _this = this;
        var _a = this.props, className = _a.className, ns = _a.classPrefix, placeholder = _a.placeholder, disabled = _a.disabled, multiple = _a.multiple, accept = _a.accept, maxLength = _a.maxLength, autoUpload = _a.autoUpload, btnUploadClassName = _a.btnUploadClassName, btnClassName = _a.btnClassName, hideUploadButton = _a.hideUploadButton;
        var _b = this.state, files = _b.files, error = _b.error, crop = _b.crop, uploading = _b.uploading, cropFile = _b.cropFile;
        var hasPending = files.some(function (file) { return file.state == 'pending'; });
        return (react_1.default.createElement("div", { className: classnames_1.default(ns + "ImageControl", className), tabIndex: -1, onPaste: this.handlePaste },
            cropFile ? (react_1.default.createElement("div", { className: "cropper-wrapper" },
                react_1.default.createElement(react_cropper_1.default, tslib_1.__assign({}, crop, { ref: "cropper", src: cropFile.preview })),
                react_1.default.createElement("button", { type: "button", className: "btn-sm btn btn-link", onClick: this.handleCrop },
                    react_1.default.createElement("i", { className: "fa fa-2x fa-check text-warning" })),
                react_1.default.createElement("button", { type: "button", className: "btn-sm btn btn-link", onClick: this.cancelCrop },
                    react_1.default.createElement("i", { className: "fa fa-2x fa-times text-white" })))) : (react_1.default.createElement(react_dropzone_1.default, { key: "drop-zone", className: classnames_1.default('drop-zone', {
                    disabled: disabled,
                    'has-files': !!files.length
                }), activeClassName: "drop-zone-active", ref: "dropzone", onDrop: this.handleDrop, onDropRejected: this.handleDropRejected, disableClick: true, accept: accept, multiple: multiple }, files && files.length ? (react_1.default.createElement("div", { className: classnames_1.default("image-list clearfix", {
                    'image-list-multiple': multiple
                }) },
                files.map(function (file, key) { return (react_1.default.createElement("div", { key: key, className: classnames_1.default('image-item pull-left', {
                        uploaded: file.state !== 'uploading',
                        invalid: file.state === 'error' || file.state == 'invalid'
                    }) },
                    react_1.default.createElement("div", { className: "img-wrapper" },
                        react_1.default.createElement("img", { onLoad: _this.handleImageLoaded.bind(_this, key), src: file.url || file.preview, alt: file.name, className: "img-rounded" })),
                    file.info ? [
                        react_1.default.createElement("p", { key: "1" },
                            file.info.width,
                            " x ",
                            file.info.height),
                        file.info.len ? (react_1.default.createElement("p", { key: "2" }, ImageControl.formatFileSize(file.info.len))) : null
                    ] : (react_1.default.createElement("p", null, "...")),
                    file.error ? (react_1.default.createElement("p", { className: "text-danger" }, file.error)) : null,
                    react_1.default.createElement("div", { className: "image-overlay" },
                        file.state === 'uploading' ? (react_1.default.createElement("i", { className: "fa fa-spinner fa-spin fa-2x fa-fw" })) : null,
                        !disabled && file.state !== 'uploading' ? (react_1.default.createElement("button", { onClick: _this.removeFile.bind(_this, file, key), type: "button", className: classnames_1.default("close", { 'crop-close': !!crop }) },
                            react_1.default.createElement("span", null, "\u00D7"))) : null,
                        !!crop && !disabled && file.state !== 'uploading' ? (react_1.default.createElement("button", { onClick: _this.editImage.bind(_this, key), type: "button", className: "edit" },
                            react_1.default.createElement("i", { className: "fa fa-pencil" }))) : null,
                        !disabled && file.state !== 'uploading' ? (react_1.default.createElement("a", { target: "_blank", href: file.url || file.preview, className: "view" },
                            react_1.default.createElement("i", { className: "fa fa-search" }))) : null))); }),
                multiple && (!maxLength || files.length < maxLength) || !multiple && !files.length ? (react_1.default.createElement("label", { className: classnames_1.default("image-add-btn", { disabled: disabled }), onClick: this.handleSelect },
                    react_1.default.createElement("i", { className: "fa fa-plus fa-3x" }))) : null)) : (react_1.default.createElement("div", { className: error ? 'text-danger' : undefined },
                error || placeholder,
                react_1.default.createElement("button", { type: "button", className: classnames_1.default('btn m-l-sm', btnClassName), disabled: disabled, onClick: this.handleSelect },
                    react_1.default.createElement("i", { className: "fa fa-cloud-upload" }),
                    " \u9009\u62E9\u6587\u4EF6"))))),
            this.renderCompressOptions(),
            !autoUpload && !hideUploadButton && files.length ? (react_1.default.createElement("button", { className: classnames_1.default('btn m-r-xs', btnUploadClassName), disabled: !hasPending, onClick: this.toggleUpload }, uploading ? '暂停上传' : '开始上传')) : null));
    };
    ImageControl.defaultProps = {
        limit: undefined,
        accept: 'image/jpeg, image/jpg, image/png, image/gif',
        reciever: '/api/upload',
        btnUploadClassName: 'btn-success',
        btnClassName: 'btn-info btn-sm',
        hideUploadButton: false,
        compressOptions: {},
        placeholder: '将图片拖入该区域，或者',
        joinValues: true,
        extractValue: false,
        delimiter: ',',
        autoUpload: true,
        multiple: false
    };
    return ImageControl;
}(react_1.default.Component));
exports.default = ImageControl;
var ImageControlRenderer = /** @class */ (function (_super) {
    tslib_1.__extends(ImageControlRenderer, _super);
    function ImageControlRenderer() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    ImageControlRenderer = tslib_1.__decorate([
        Item_1.FormItem({
            type: 'image',
            sizeMutable: false
        })
    ], ImageControlRenderer);
    return ImageControlRenderer;
}(ImageControl));
exports.ImageControlRenderer = ImageControlRenderer;
;
//# sourceMappingURL=./renderers/Form/Image.js.map
