import { __decorate } from 'tslib';
import { EventEmitter, Renderer2, ElementRef, ChangeDetectorRef, NgZone, ViewChild, Input, Output, HostListener, Component, ChangeDetectionStrategy, NgModule } from '@angular/core';
import { st2c, StyleCollection, LY_COMMON_STYLES, mergeDeep, LyTheme2, LyHammerGestureConfig } from '@alyle/ui';
import { Subject, Observable } from 'rxjs';
import { take, takeUntil } from 'rxjs/operators';
import { HAMMER_GESTURE_CONFIG } from '@angular/platform-browser';
import { CommonModule } from '@angular/common';

const STYLE_PRIORITY = -2;
const STYLES = (theme, ref) => {
    const cropper = ref.selectorsOf(STYLES);
    return {
        $name: LyImageCropper.и,
        $priority: STYLE_PRIORITY,
        root: () => (className) => `${className}{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;display:flex;overflow:hidden;position:relative;justify-content:center;align-items:center;}${st2c(((theme.cropper
            && theme.cropper.root
            && (theme.cropper.root instanceof StyleCollection
                ? theme.cropper.root.setTransformer(fn => fn(cropper))
                : theme.cropper.root(cropper)))), `${className}`)}`,
        imgContainer: (className) => `${className}{cursor:move;position:absolute;top:0;left:0;}${className} > canvas{pointer-events:none;}`,
        area: (className) => `${className}{pointer-events:none;box-shadow:0 0 0 20000px rgba(0, 0, 0, 0.4);margin:auto;}${st2c((LY_COMMON_STYLES.fill), `${className}`)}${st2c((LY_COMMON_STYLES.fill), `${className}:before,${className}:after`)}${className}:before,${className}:after{content:'';}${className}:before{width:0;height:0;margin:auto;border-radius:50%;background:#fff;border:solid 2px rgb(255, 255, 255);}${className}:after{border:solid 2px rgb(255, 255, 255);}`,
        defaultContent: (className) => `${className}{display:flex;align-items:center;justify-content:center;}${st2c((LY_COMMON_STYLES.fill), `${className},${className} > input`)}${className} *:not(input){pointer-events:none;}${className} > input{background:transparent;opacity:0;width:100%;height:100%;}`
    };
};
/** Image output */
var ImgResolution;
(function (ImgResolution) {
    /** Resizing & cropping */
    ImgResolution[ImgResolution["Default"] = 0] = "Default";
    /** Only cropping */
    ImgResolution[ImgResolution["OriginalImage"] = 1] = "OriginalImage";
})(ImgResolution || (ImgResolution = {}));
/** Image output */
var ImgCropperError;
(function (ImgCropperError) {
    /** The loaded image exceeds the size limit set. */
    ImgCropperError[ImgCropperError["Size"] = 0] = "Size";
    /** The file loaded is not image. */
    ImgCropperError[ImgCropperError["Type"] = 1] = "Type";
    /** When the image has not been loaded. */
    ImgCropperError[ImgCropperError["Other"] = 2] = "Other";
})(ImgCropperError || (ImgCropperError = {}));
const CONFIG_DEFAULT = {
    width: 250,
    height: 200,
    output: ImgResolution.Default,
    antiAliased: true
};
let LyImageCropper = class LyImageCropper {
    constructor(_renderer, theme, elementRef, cd, _ngZone) {
        this._renderer = _renderer;
        this.theme = theme;
        this.elementRef = elementRef;
        this.cd = cd;
        this._ngZone = _ngZone;
        /**
         * styles
         * @docs-private
         */
        this.classes = this.theme.addStyleSheet(STYLES);
        this._imgRect = {};
        this._listeners = new Set();
        this.scaleChange = new EventEmitter();
        /** On loaded new image */
        this.loaded = new EventEmitter();
        /** On crop new image */
        this.cropped = new EventEmitter();
        /** Emit an error when the loaded image is not valid */
        this.error = new EventEmitter();
        /** Emits whenever the component is destroyed. */
        this._destroy = new Subject();
        this._renderer.addClass(elementRef.nativeElement, this.classes.root);
    }
    get config() {
        return this._config;
    }
    set config(val) {
        this._config = mergeDeep({}, CONFIG_DEFAULT, val);
        const maxFileSize = this._config.maxFileSize;
        if (maxFileSize) {
            this.maxFileSize = maxFileSize;
        }
    }
    /** Set scale */
    get scale() {
        return this._scale;
    }
    set scale(val) {
        this.setScale(val);
    }
    /** Get min scale */
    get minScale() {
        return this._minScale;
    }
    ngOnDestroy() {
        this._destroy.next();
        this._destroy.complete();
    }
    _removeListeners() {
        this._listeners.forEach(listen => listen.unsubscribe());
        this._listeners.clear();
    }
    _imgLoaded(imgElement) {
        if (imgElement) {
            this._img = imgElement;
            const canvas = this._imgCanvas.nativeElement;
            canvas.width = imgElement.width;
            canvas.height = imgElement.height;
            const ctx = canvas.getContext('2d');
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            ctx.drawImage(imgElement, 0, 0);
            /** set min scale */
            this._updateMinScale(canvas);
        }
    }
    _setStylesForContImg(values) {
        const newStyles = {};
        if (values.x !== void 0 && values.y !== void 0) {
            const rootRect = this._rootRect();
            const x = rootRect.width / 2 - (values.x);
            const y = rootRect.height / 2 - (values.y);
            this._imgRect.x = (values.x);
            this._imgRect.y = (values.y);
            this._imgRect.xc = (x);
            this._imgRect.yc = (y);
        }
        newStyles.transform = `translate3d(${(this._imgRect.x)}px,${(this._imgRect.y)}px, 0)`;
        newStyles.transform += `scale(${this._scal3Fix})`;
        newStyles.transformOrigin = `${this._imgRect.xc}px ${this._imgRect.yc}px 0`;
        newStyles['-webkit-transform'] = newStyles.transform;
        newStyles['-webkit-transform-origin'] = newStyles.transformOrigin;
        for (const key in newStyles) {
            if (newStyles.hasOwnProperty(key)) {
                this._renderer.setStyle(this._imgContainer.nativeElement, key, newStyles[key]);
            }
        }
    }
    _resize$() {
        if (this.isLoaded) {
            this.updatePosition();
        }
    }
    selectInputEvent(img) {
        this._ngZone.onStable.pipe(take(1), takeUntil(this._destroy)).subscribe(() => {
            this._currentInputElement = img.target;
            const _img = img.target;
            if (_img.files && _img.files.length !== 1) {
                return;
            }
            const fileSize = _img.files[0].size;
            const fileName = _img.value.replace(/.*(\/|\\)/, '');
            if (this.maxFileSize && fileSize > this.maxFileSize) {
                const cropEvent = {
                    name: fileName,
                    type: _img.files[0].type,
                    size: fileSize,
                    error: ImgCropperError.Size
                };
                this.clean();
                this.error.emit(cropEvent);
                return;
            }
            const readFile = new Observable(obs => {
                const reader = new FileReader();
                reader.onerror = err => obs.error(err);
                reader.onabort = err => obs.error(err);
                reader.onload = (ev) => setTimeout(() => {
                    obs.next(ev);
                    obs.complete();
                }, 1);
                return reader.readAsDataURL(_img.files[0]);
            })
                .subscribe({
                next: (loadEvent) => {
                    const originalImageUrl = loadEvent.target.result;
                    // Set type
                    if (!this.config.type) {
                        this._defaultType = _img.files[0].type;
                    }
                    // set name
                    this._fileName = fileName;
                    // set file size
                    this._sizeInBytes = _img.files[0].size;
                    this.setImageUrl(originalImageUrl);
                    this.cd.markForCheck();
                    this._listeners.delete(readFile);
                },
                error: () => {
                    const cropEvent = {
                        name: fileName,
                        size: fileSize,
                        error: ImgCropperError.Other,
                        errorMsg: 'The File could not be loaded.'
                    };
                    this.clean();
                    this.error.emit(cropEvent);
                    this._listeners.delete(readFile);
                    this._removeListeners();
                }
            });
            this._listeners.add(readFile);
        });
    }
    /** Set the size of the image, the values can be 0 between 1, where 1 is the original size */
    setScale(size, noAutoCrop) {
        // fix min scale
        const newSize = size >= this.minScale && size <= 1 ? size : this.minScale;
        // check
        const changed = size != null && size !== this.scale && newSize !== this.scale;
        this._scale = size;
        if (!changed) {
            return;
        }
        this._scal3Fix = newSize;
        if (this.isLoaded) {
            if (changed) {
                const originPosition = Object.assign({}, this._imgRect);
                this.offset = {
                    x: originPosition.x,
                    y: originPosition.y,
                    left: originPosition.xc,
                    top: originPosition.yc
                };
                this._setStylesForContImg({});
                this._move({
                    srcEvent: {},
                    deltaX: 0,
                    deltaY: 0
                });
            }
            else {
                return;
            }
        }
        else if (this.minScale) {
            this._setStylesForContImg(Object.assign({}, this._getCenterPoints()));
        }
        else {
            return;
        }
        this.scaleChange.emit(size);
        if (!noAutoCrop) {
            this._cropIfAutoCrop();
        }
    }
    _getCenterPoints() {
        const root = this.elementRef.nativeElement;
        const img = this._imgCanvas.nativeElement;
        const x = (root.offsetWidth - (img.width)) / 2;
        const y = (root.offsetHeight - (img.height)) / 2;
        return {
            x,
            y
        };
    }
    /**
     * Ajustar a la pantalla
     */
    fitToScreen() {
        const container = this.elementRef.nativeElement;
        const min = {
            width: container.offsetWidth,
            height: container.offsetHeight
        };
        const { width, height } = this._img;
        const minScale = {
            width: min.width / width,
            height: min.height / height
        };
        const result = Math.max(minScale.width, minScale.height);
        this.setScale(result);
    }
    fit() {
        this.setScale(this.minScale);
    }
    _moveStart() {
        this.offset = {
            x: this._imgRect.x,
            y: this._imgRect.y,
            left: this._imgRect.xc,
            top: this._imgRect.yc
        };
    }
    _move(event) {
        let x, y;
        const canvas = this._imgCanvas.nativeElement;
        const scaleFix = this._scal3Fix;
        const config = this.config;
        const startP = this.offset;
        if (!scaleFix || !startP) {
            return;
        }
        const isMinScaleY = canvas.height * scaleFix < config.height && config.extraZoomOut;
        const isMinScaleX = canvas.width * scaleFix < config.width && config.extraZoomOut;
        const limitLeft = (config.width / 2 / scaleFix) >= startP.left - (event.deltaX / scaleFix);
        const limitRight = (config.width / 2 / scaleFix) + (canvas.width) - (startP.left - (event.deltaX / scaleFix)) <= config.width / scaleFix;
        const limitTop = ((config.height / 2 / scaleFix) >= (startP.top - (event.deltaY / scaleFix)));
        const limitBottom = (((config.height / 2 / scaleFix) + (canvas.height) - (startP.top - (event.deltaY / scaleFix))) <= (config.height / scaleFix));
        // Limit for left
        if ((limitLeft && !isMinScaleX) || (!limitLeft && isMinScaleX)) {
            x = startP.x + (startP.left) - (config.width / 2 / scaleFix);
        }
        // Limit for right
        if ((limitRight && !isMinScaleX) || (!limitRight && isMinScaleX)) {
            x = startP.x + (startP.left) + (config.width / 2 / scaleFix) - canvas.width;
        }
        // Limit for top
        if ((limitTop && !isMinScaleY) || (!limitTop && isMinScaleY)) {
            y = startP.y + (startP.top) - (config.height / 2 / scaleFix);
        }
        // Limit for bottom
        if ((limitBottom && !isMinScaleY) || (!limitBottom && isMinScaleY)) {
            y = startP.y + (startP.top) + (config.height / 2 / scaleFix) - canvas.height;
        }
        // When press shiftKey, deprecated
        // if (event.srcEvent && event.srcEvent.shiftKey) {
        //   if (Math.abs(event.deltaX) === Math.max(Math.abs(event.deltaX), Math.abs(event.deltaY))) {
        //     y = this.offset.top;
        //   } else {
        //     x = this.offset.left;
        //   }
        // }
        if (x === void 0) {
            x = (event.deltaX / scaleFix) + (startP.x);
        }
        if (y === void 0) {
            y = (event.deltaY / scaleFix) + (startP.y);
        }
        this._setStylesForContImg({
            x, y
        });
    }
    updatePosition(x, y) {
        const hostRect = this._rootRect();
        const croppingContainerRect = this._areaCropperRect();
        if (x === undefined && y === undefined) {
            x = this._imgRect.xc;
            y = this._imgRect.yc;
        }
        x = (croppingContainerRect.left - hostRect.left) - (x - (this.config.width / 2));
        y = (croppingContainerRect.top - hostRect.top) - (y - (this.config.height / 2));
        this._setStylesForContImg({
            x, y
        });
    }
    _slideEnd() {
        this._cropIfAutoCrop();
    }
    _cropIfAutoCrop() {
        if (this.config.autoCrop) {
            this.crop();
        }
    }
    /**+ */
    zoomIn() {
        const scale = this._scal3Fix + .05;
        if (scale > 0 && scale <= 1) {
            this.setScale(scale);
        }
        else {
            this.setScale(1);
        }
    }
    /** Clean the img cropper */
    clean() {
        // fix choosing the same image does not load
        if (this._currentInputElement) {
            this._currentInputElement.value = '';
            this._currentInputElement = null;
        }
        if (this.isLoaded) {
            this._imgRect = {};
            this.offset = undefined;
            this.scale = undefined;
            this._scal3Fix = undefined;
            this._rotation = 0;
            this._minScale = undefined;
            this._isLoadedImg = false;
            this.isLoaded = false;
            this.isCropped = false;
            this._originalImgBase64 = undefined;
            const canvas = this._imgCanvas.nativeElement;
            canvas.width = 0;
            canvas.height = 0;
            this.cd.markForCheck();
        }
    }
    /**- */
    zoomOut() {
        const scale = this._scal3Fix - .05;
        if (scale > this.minScale && scale <= 1) {
            this.setScale(scale);
        }
        else {
            this.fit();
        }
    }
    center() {
        const newStyles = Object.assign({}, this._getCenterPoints());
        this._setStylesForContImg(newStyles);
        this._cropIfAutoCrop();
    }
    /**
     * Load Image from URL
     * @param src URL
     * @param fn function that will be called before emit the event loaded
     */
    setImageUrl(src, fn) {
        this.clean();
        this._originalImgBase64 = src;
        src = normalizeSVG(src);
        const img = createHtmlImg(src);
        const fileSize = this._sizeInBytes;
        const fileName = this._fileName;
        const defaultType = this._defaultType;
        const cropEvent = {
            name: fileName,
            type: defaultType,
            originalDataURL: src
        };
        if (fileSize) {
            cropEvent.size = fileSize;
        }
        const loadListen = new Observable(obs => {
            img.onerror = err => obs.error(err);
            img.onabort = err => obs.error(err);
            img.onload = () => {
                obs.next(null);
                obs.complete();
            };
        })
            .subscribe({
            next: () => {
                this._imgLoaded(img);
                cropEvent.width = img.width;
                cropEvent.height = img.height;
                this._isLoadedImg = true;
                this.cd.markForCheck();
                this._ngZone
                    .onStable
                    .pipe(take(1))
                    .subscribe(() => setTimeout(() => this._ngZone.run(() => {
                    this._updateMinScale(this._imgCanvas.nativeElement);
                    this.isLoaded = false;
                    if (fn) {
                        fn();
                    }
                    else {
                        this.setScale(this.minScale, true);
                    }
                    this.loaded.emit(cropEvent);
                    this.isLoaded = true;
                    this._cropIfAutoCrop();
                    this.cd.markForCheck();
                }), 0));
                this._listeners.delete(loadListen);
                this._removeListeners();
            },
            error: () => {
                cropEvent.error = ImgCropperError.Type;
                this.error.emit(cropEvent);
                this._listeners.delete(loadListen);
                this._removeListeners();
            }
        });
        this._listeners.add(loadListen);
        // clear
        this._sizeInBytes = null;
        this._fileName = null;
        this._defaultType = undefined;
    }
    rotate(degrees) {
        const validDegrees = this._rotation = convertToValidDegrees(degrees);
        const degreesRad = validDegrees * Math.PI / 180;
        const canvas = this._imgCanvas.nativeElement;
        const canvasClon = createCanvasImg(canvas);
        const ctx = canvas.getContext('2d');
        // clear
        ctx.clearRect(0, 0, canvasClon.width, canvasClon.height);
        // rotate canvas image
        const transform = `rotate(${validDegrees}deg) scale(${1 / this._scal3Fix})`;
        const transformOrigin = `${this._imgRect.xc}px ${this._imgRect.yc}px 0`;
        canvas.style.transform = transform;
        canvas.style.webkitTransform = transform;
        canvas.style.transformOrigin = transformOrigin;
        canvas.style.webkitTransformOrigin = transformOrigin;
        const { left, top } = canvas.getBoundingClientRect();
        // save rect
        const canvasRect = canvas.getBoundingClientRect();
        // remove rotate styles
        canvas.removeAttribute('style');
        // set w & h
        const w = canvasRect.width;
        const h = canvasRect.height;
        ctx.canvas.width = w;
        ctx.canvas.height = h;
        // clear
        ctx.clearRect(0, 0, w, h);
        // translate and rotate
        ctx.translate(w / 2, h / 2);
        ctx.rotate(degreesRad);
        ctx.drawImage(canvasClon, -canvasClon.width / 2, -canvasClon.height / 2);
        // Update min scale
        this._updateMinScale(canvas);
        // set the minimum scale, only if necessary
        if (this.scale < this.minScale) {
            this.setScale(0, true);
        } //                ↑ no AutoCrop
        const rootRect = this._rootRect();
        this._setStylesForContImg({
            x: (left - rootRect.left),
            y: (top - rootRect.top)
        });
        // keep image inside the frame
        const originPosition = Object.assign({}, this._imgRect);
        this.offset = {
            x: originPosition.x,
            y: originPosition.y,
            left: originPosition.xc,
            top: originPosition.yc
        };
        this._setStylesForContImg({});
        this._move({
            srcEvent: {},
            deltaX: 0,
            deltaY: 0
        });
        this._cropIfAutoCrop();
    }
    _updateMinScale(canvas) {
        const config = this.config;
        this._minScale = (config.extraZoomOut ? Math.min : Math.max)(config.width / canvas.width, config.height / canvas.height);
    }
    imageSmoothingQuality(img, config, quality) {
        /** Calculate total number of steps needed */
        let numSteps = Math.ceil(Math.log(Math.max(img.width, img.height) / Math.max(config.width, config.height)) / Math.log(2)) - 1;
        numSteps = numSteps <= 0 ? 0 : numSteps;
        /**Array steps */
        const steps = Array.from(Array(numSteps).keys());
        /** Context */
        const octx = img.getContext('2d');
        const q = (Math.pow((quality * 10), numSteps)) / (Math.pow(10, numSteps));
        const fileType = this._defaultType;
        /** If Steps => imageSmoothingQuality */
        if (numSteps) {
            /** Set size */
            const w = img.width * quality;
            const h = img.height * quality;
            /** Only the new img is shown. */
            if (fileType === 'image/png' || fileType === 'image/svg+xml') {
                octx.globalCompositeOperation = 'copy';
            }
            /** Steps */
            steps.forEach(() => {
                octx.drawImage(img, 0, 0, w, h);
            });
        }
        /**
         * Step final
         * Resize & crop image
         */
        const oc = document.createElement('canvas'), ctx = oc.getContext('2d');
        oc.width = config.width;
        oc.height = config.height;
        ctx.drawImage(img, 0, 0, img.width * q, img.height * q, 0, 0, oc.width, oc.height);
        return oc;
    }
    /**
     * Crop Image
     * Resize & crop image
     */
    crop(config) {
        const newConfig = config ? mergeDeep({}, this.config || CONFIG_DEFAULT, config) : this.config;
        const cropEvent = this._imgCrop(newConfig);
        this.cd.markForCheck();
        return cropEvent;
    }
    /**
     * @docs-private
     */
    _imgCrop(myConfig) {
        const canvasElement = document.createElement('canvas');
        const imgRect = this._imgRect;
        const scaleFix = this._scal3Fix;
        const left = imgRect.xc - (myConfig.width / 2 / scaleFix);
        const top = imgRect.yc - (myConfig.height / 2 / scaleFix);
        const config = {
            width: myConfig.width,
            height: myConfig.height
        };
        canvasElement.width = config.width / scaleFix;
        canvasElement.height = config.height / scaleFix;
        const ctx = canvasElement.getContext('2d');
        if (myConfig.fill) {
            ctx.fillStyle = myConfig.fill;
            ctx.fillRect(0, 0, canvasElement.width, canvasElement.height);
        }
        ctx.drawImage(this._imgCanvas.nativeElement, -(left), -(top));
        let result = canvasElement;
        const antiAliasedQ = myConfig.antiAliased ? .5 : 1;
        if (myConfig.output === 0) {
            result = this.imageSmoothingQuality(result, config, antiAliasedQ);
        }
        else if (typeof myConfig.output === 'object') {
            result = this.imageSmoothingQuality(result, myConfig.output, antiAliasedQ);
        }
        let url;
        if (myConfig.type) {
            url = result.toDataURL(`${myConfig.type}`);
        }
        else {
            url = result.toDataURL(this._defaultType);
        }
        const cropEvent = {
            dataURL: url,
            type: this._defaultType || myConfig.type,
            name: this._fileName,
            width: config.width,
            height: config.height,
            originalDataURL: this._originalImgBase64,
            scale: this._scal3Fix,
            rotation: this._rotation,
            position: {
                x: this._imgRect.xc,
                y: this._imgRect.yc
            }
        };
        this.isCropped = true;
        this.cropped.emit(cropEvent);
        return cropEvent;
    }
    _rootRect() {
        return this.elementRef.nativeElement.getBoundingClientRect();
    }
    _areaCropperRect() {
        return this._croppingContainer.nativeElement.getBoundingClientRect();
    }
};
LyImageCropper.и = 'LyImageCropper';
LyImageCropper.ctorParameters = () => [
    { type: Renderer2 },
    { type: LyTheme2 },
    { type: ElementRef },
    { type: ChangeDetectorRef },
    { type: NgZone }
];
__decorate([
    ViewChild('_imgContainer', { static: true })
], LyImageCropper.prototype, "_imgContainer", void 0);
__decorate([
    ViewChild('_area')
], LyImageCropper.prototype, "_croppingContainer", void 0);
__decorate([
    ViewChild('_imgCanvas', { static: true })
], LyImageCropper.prototype, "_imgCanvas", void 0);
__decorate([
    Input()
], LyImageCropper.prototype, "config", null);
__decorate([
    Input()
], LyImageCropper.prototype, "scale", null);
__decorate([
    Input()
], LyImageCropper.prototype, "maxFileSize", void 0);
__decorate([
    Output()
], LyImageCropper.prototype, "scaleChange", void 0);
__decorate([
    Output()
], LyImageCropper.prototype, "loaded", void 0);
__decorate([
    Output()
], LyImageCropper.prototype, "cropped", void 0);
__decorate([
    Output()
], LyImageCropper.prototype, "error", void 0);
__decorate([
    HostListener('window:resize')
], LyImageCropper.prototype, "_resize$", null);
LyImageCropper = __decorate([
    Component({
        changeDetection: ChangeDetectionStrategy.OnPush,
        preserveWhitespaces: false,
        selector: 'ly-img-cropper, ly-image-cropper',
        template: "<div #_imgContainer\n[className]=\"classes.imgContainer\"\n(slidestart)=\"_moveStart()\"\n(slide)=\"_move($event)\"\n(slideend)=\"_slideEnd()\">\n  <canvas #_imgCanvas></canvas>\n</div>\n<div #_area *ngIf=\"_isLoadedImg; else content\" [className]=\"classes.area\" [ngStyle]=\"{\n  width: config.width + 'px',\n  height: config.height + 'px'\n}\"></div>\n<ng-template #content>\n  <div [className]=\"classes.defaultContent\">\n    <input #_fileInput type=\"file\" (change)=\"selectInputEvent($event)\" accept=\"image/*\">\n    <ng-content></ng-content>\n  </div>\n</ng-template>\n"
    })
], LyImageCropper);
/**
 * convertToValidDegrees(45) === 90
 * convertToValidDegrees(40) === 0
 * convertToValidDegrees(100) === 90
 * @docs-private
 */
function convertToValidDegrees(num) {
    const val360 = limitNum(num, 360);
    const val90 = limitNum(val360.result, 90);
    const sign = Math.sign(num);
    if (val90.result >= (90 / 2)) {
        return 90 * (val90.parts + 1) * sign;
    }
    else {
        return 90 * val90.parts * sign;
    }
}
/**
 * demo:
 * limitNum(450, 360) === 90
 * @docs-private
 */
function limitNum(num, num2) {
    const numAbs = Math.abs(num);
    const parts = Math.floor(numAbs / num2);
    let result;
    if (parts) {
        result = numAbs - (num2 * parts);
    }
    else {
        result = num;
    }
    if (numAbs !== num) {
        result *= -1;
    }
    return {
        result,
        parts
    };
}
/**
 * @docs-private
 */
function createCanvasImg(img) {
    // create a new canvas
    const newCanvas = document.createElement('canvas');
    const context = newCanvas.getContext('2d');
    // set dimensions
    newCanvas.width = img.width;
    newCanvas.height = img.height;
    // apply the old canvas to the new one
    context.drawImage(img, 0, 0);
    // return the new canvas
    return newCanvas;
}
const DATA_IMAGE_SVG_PREFIX = 'data:image/svg+xml;base64,';
function normalizeSVG(dataURL) {
    if (window.atob && isSvgImage(dataURL)) {
        const len = dataURL.length / 5;
        const text = window.atob(dataURL.replace(DATA_IMAGE_SVG_PREFIX, ''));
        const span = document.createElement('span');
        span.innerHTML = text;
        const svg = span.querySelector('svg');
        span.setAttribute('style', 'display:none');
        document.body.appendChild(span);
        const width = parseFloat(getComputedStyle(svg).width) || 1;
        const height = parseFloat(getComputedStyle(svg).height) || 1;
        const max = Math.max(width, height);
        svg.setAttribute('width', `${len / (width / max)}px`);
        svg.setAttribute('height', `${len / (height / max)}px`);
        const result = DATA_IMAGE_SVG_PREFIX + window.btoa(span.innerHTML);
        document.body.removeChild(span);
        return result;
    }
    return dataURL;
}
function isSvgImage(dataUrl) {
    return dataUrl.startsWith(DATA_IMAGE_SVG_PREFIX);
}
function createHtmlImg(src) {
    const img = new Image();
    img.crossOrigin = 'anonymous';
    img.src = src;
    return img;
}

let LyImageCropperModule = class LyImageCropperModule {
};
LyImageCropperModule = __decorate([
    NgModule({
        imports: [CommonModule],
        exports: [LyImageCropper],
        providers: [
            { provide: HAMMER_GESTURE_CONFIG, useClass: LyHammerGestureConfig }
        ],
        declarations: [LyImageCropper]
    })
], LyImageCropperModule);

/**
 * Generated bundle index. Do not edit.
 */

export { ImgCropperError, ImgResolution, LyImageCropper, LyImageCropperModule, STYLES };
//# sourceMappingURL=alyle-ui-image-cropper.js.map
