import { Injectable, Optional, Inject, PLATFORM_ID, ɵɵdefineInjectable, ɵɵinject } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
import { __awaiter, __generator, __extends, __spread } from 'tslib';
import { mapTo, map, distinctUntilChanged, shareReplay, debounceTime, startWith } from 'rxjs/operators';
import { of, fromEvent, Observable, merge } from 'rxjs';

/**
 * @fileoverview added by tsickle
 * Generated from: lib/core/services/platform.service.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
/** @type {?} */
var hasV8BreakIterator = (typeof Intl !== 'undefined' && ((/** @type {?} */ (Intl))).v8BreakIterator);
var Platform = /** @class */ (function () {
    function Platform(_platformId) {
        this._platformId = _platformId;
    }
    Object.defineProperty(Platform.prototype, "isBrowser", {
        // Browser check.
        get: 
        // Browser check.
        /**
         * @return {?}
         */
        function () {
            return this._platformId
                ? isPlatformBrowser(this._platformId)
                : typeof document === 'object' && !!document;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(Platform.prototype, "isTrident", {
        // Rendering engines.
        get: 
        // Rendering engines.
        /**
         * @return {?}
         */
        function () {
            return this.isBrowser && /(msie|trident)/i.test(navigator.userAgent);
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(Platform.prototype, "isBlink", {
        get: /**
         * @return {?}
         */
        function () {
            return this.isBrowser && (!!(((/** @type {?} */ (window))).chrome || hasV8BreakIterator) &&
                typeof CSS !== 'undefined' && !this.isEdge && !this.isTrident);
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(Platform.prototype, "isWebkit", {
        get: /**
         * @return {?}
         */
        function () {
            return this.isBrowser && /AppleWebKit/i.test(navigator.userAgent)
                && !this.isBlink && !this.isEdge && !this.isTrident;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(Platform.prototype, "isChrome", {
        // Browsers.
        get: 
        // Browsers.
        /**
         * @return {?}
         */
        function () {
            return this.isBrowser && /Google Inc./.test(navigator.vendor);
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(Platform.prototype, "isEdge", {
        get: /**
         * @return {?}
         */
        function () {
            return this.isBrowser && /(edge)/i.test(navigator.userAgent);
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(Platform.prototype, "isFirefox", {
        get: /**
         * @return {?}
         */
        function () {
            return this.isBrowser && /(firefox|minefield)/i.test(navigator.userAgent);
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(Platform.prototype, "isSafari", {
        get: /**
         * @return {?}
         */
        function () {
            return this.isBrowser && /safari/i.test(navigator.userAgent) && this.isWebkit;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(Platform.prototype, "isIos", {
        // Platforms.
        get: 
        // Platforms.
        /**
         * @return {?}
         */
        function () {
            return this.isBrowser && /iPad|iPhone|iPod/.test(navigator.userAgent) && !('MSStream' in window);
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(Platform.prototype, "isAndroid", {
        get: /**
         * @return {?}
         */
        function () {
            return this.isBrowser && /android/i.test(navigator.userAgent) && !this.isTrident;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(Platform.prototype, "isDesktop", {
        get: /**
         * @return {?}
         */
        function () {
            return this.isBrowser && !(/(iPhone|iPod|iPad|Android|BlackBerry|IEMobile)/.test(navigator.userAgent));
        },
        enumerable: true,
        configurable: true
    });
    Platform.decorators = [
        { type: Injectable, args: [{
                    providedIn: 'root'
                },] }
    ];
    /** @nocollapse */
    Platform.ctorParameters = function () { return [
        { type: Object, decorators: [{ type: Optional }, { type: Inject, args: [PLATFORM_ID,] }] }
    ]; };
    /** @nocollapse */ Platform.ngInjectableDef = ɵɵdefineInjectable({ factory: function Platform_Factory() { return new Platform(ɵɵinject(PLATFORM_ID, 8)); }, token: Platform, providedIn: "root" });
    return Platform;
}());
if (false) {
    /**
     * @type {?}
     * @private
     */
    Platform.prototype._platformId;
}

/**
 * @fileoverview added by tsickle
 * Generated from: lib/core/services/image-converter.service.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
var ImageConverter = /** @class */ (function () {
    function ImageConverter(_platform) {
        this._platform = _platform;
        // Data.
        this._types = ['image/png', 'image/jpeg'];
        this.calculateOffsetAndDimensions = (/**
         * @param {?} image
         * @param {?} canvasWidth
         * @param {?} canvasHeight
         * @return {?}
         */
        function (image, canvasWidth, canvasHeight) {
            /** @type {?} */
            var originalWidth = image.width;
            /** @type {?} */
            var originalHeight = image.height;
            /** @type {?} */
            var widthRatio = canvasWidth / originalWidth;
            /** @type {?} */
            var heightRatio = canvasHeight / originalHeight;
            /** @type {?} */
            var width = 0;
            /** @type {?} */
            var height = 0;
            if (originalWidth > originalHeight) {
                height = originalHeight * heightRatio;
                width = (originalWidth / originalHeight) * height;
            }
            else {
                width = originalWidth * widthRatio;
                height = (originalHeight / originalWidth) * width;
            }
            /** @type {?} */
            var xOffset = 0;
            /** @type {?} */
            var yOffset = 0;
            if (canvasHeight === height) {
                xOffset = -((width - canvasWidth) / 2);
            }
            else if (canvasWidth === width) {
                yOffset = -((height - canvasHeight) / 2);
            }
            return { xOffset: xOffset, yOffset: yOffset, width: width, height: height };
        });
    }
    /**
     * @param {?} contents
     * @param {?=} options
     * @return {?}
     */
    ImageConverter.prototype.toDataUri = /**
     * @param {?} contents
     * @param {?=} options
     * @return {?}
     */
    function (contents, options) {
        if (options === void 0) { options = null; }
        return __awaiter(this, void 0, void 0, function () {
            var image, canvasWidth, canvasHeight, canvas, context, _a, width, height, xOffset, yOffset;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        // Check if the current platform is a browser.
                        if (!this._platform.isBrowser) {
                            return [2 /*return*/, null];
                        }
                        // Get the image.
                        return [4 /*yield*/, this.getImage(contents)];
                    case 1:
                        image = _b.sent();
                        // Get the canvas width and height.
                        canvasWidth = (options && options.width) || image.width;
                        canvasHeight = (options && options.height) || image.height;
                        // Get the canvas and context.
                        canvas = document.createElement('canvas');
                        context = canvas.getContext('2d');
                        canvas.width = canvasWidth;
                        canvas.height = canvasHeight;
                        // Check if dimensions where supplied, else create the image.
                        if (!options) {
                            // Draw the image.
                            context.drawImage(image, 0, 0);
                            // Convert the canvas to a data url.
                            return [2 /*return*/, canvas.toDataURL(this._types[0])];
                        }
                        // Get the dimensions and offsets.
                        _a = this.calculateOffsetAndDimensions(image, canvasWidth, canvasHeight), width = _a.width, height = _a.height, xOffset = _a.xOffset, yOffset = _a.yOffset;
                        // Draw the image.
                        context.drawImage(image, 0, 0, image.width, image.height, xOffset, yOffset, width, height);
                        // Convert the canvas to a data url.
                        return [2 /*return*/, canvas.toDataURL(this._types[0])];
                }
            });
        });
    };
    /**
     * @param {?} file
     * @param {?=} types
     * @return {?}
     */
    ImageConverter.prototype.fileToImage = /**
     * @param {?} file
     * @param {?=} types
     * @return {?}
     */
    function (file, types) {
        var _this = this;
        if (types === void 0) { types = this._types; }
        return new Promise((/**
         * @param {?} resolve
         * @param {?} reject
         * @return {?}
         */
        function (resolve, reject) {
            // Check if the file matches an image.
            if (!types.includes(file.type)) {
                return reject('The selected file does not meet the required format.');
            }
            /** @type {?} */
            var fileReader = new FileReader();
            fileReader.readAsDataURL(file);
            fileReader.onloadend = (/**
             * @param {?} data
             * @return {?}
             */
            function (data) { return __awaiter(_this, void 0, void 0, function () {
                var dataUri, image;
                return __generator(this, function (_a) {
                    switch (_a.label) {
                        case 0:
                            // Get the data URI.
                            dataUri = data.target['result'];
                            // Convert the data URI to a image element.
                            return [4 /*yield*/, this.stringToImage(dataUri)];
                        case 1:
                            image = _a.sent();
                            // Resolve the image.
                            return [2 /*return*/, resolve(image)];
                    }
                });
            }); });
            fileReader.onerror = (/**
             * @param {?} error
             * @return {?}
             */
            function (error) { return reject(error); });
        }));
    };
    /**
     * @param {?} src
     * @return {?}
     */
    ImageConverter.prototype.stringToImage = /**
     * @param {?} src
     * @return {?}
     */
    function (src) {
        return new Promise((/**
         * @param {?} resolve
         * @param {?} reject
         * @return {?}
         */
        function (resolve, reject) {
            /** @type {?} */
            var image = new Image();
            image.src = src;
            image.onload = (/**
             * @return {?}
             */
            function () { return resolve(image); });
            image.onerror = (/**
             * @param {?} error
             * @return {?}
             */
            function (error) { return reject(error); });
        }));
    };
    /**
     * @private
     * @param {?} contents
     * @return {?}
     */
    ImageConverter.prototype.getImage = /**
     * @private
     * @param {?} contents
     * @return {?}
     */
    function (contents) {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                // If the contents is already an HTML image element just return it.
                if (contents instanceof HTMLImageElement) {
                    return [2 /*return*/, contents];
                }
                // If the contents is a file convert it to an HTML image element.
                if (contents instanceof File) {
                    return [2 /*return*/, this.fileToImage(contents)];
                }
                // If the contents is a string convert it to an HTML image element.
                if (typeof contents === 'string') {
                    return [2 /*return*/, this.stringToImage(contents)];
                }
                return [2 /*return*/];
            });
        });
    };
    ImageConverter.decorators = [
        { type: Injectable, args: [{
                    providedIn: 'root'
                },] }
    ];
    /** @nocollapse */
    ImageConverter.ctorParameters = function () { return [
        { type: Platform }
    ]; };
    /** @nocollapse */ ImageConverter.ngInjectableDef = ɵɵdefineInjectable({ factory: function ImageConverter_Factory() { return new ImageConverter(ɵɵinject(Platform)); }, token: ImageConverter, providedIn: "root" });
    return ImageConverter;
}());
if (false) {
    /**
     * @type {?}
     * @private
     */
    ImageConverter.prototype._types;
    /**
     * @type {?}
     * @private
     */
    ImageConverter.prototype.calculateOffsetAndDimensions;
    /**
     * @type {?}
     * @private
     */
    ImageConverter.prototype._platform;
}

/**
 * @fileoverview added by tsickle
 * Generated from: lib/core/services/file-loader.service.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
var FileLoader = /** @class */ (function () {
    function FileLoader() {
    }
    /**
     * @param {?} dataUri
     * @param {?=} name
     * @return {?}
     */
    FileLoader.prototype.toFile = /**
     * @param {?} dataUri
     * @param {?=} name
     * @return {?}
     */
    function (dataUri, name) {
        if (name === void 0) { name = 'file'; }
        try {
            /** @type {?} */
            var arr = dataUri.split(',');
            /** @type {?} */
            var mime = arr[0].match(/:(.*?);/)[1];
            /** @type {?} */
            var bstr = atob(arr[1]);
            /** @type {?} */
            var n = bstr.length;
            /** @type {?} */
            var u8arr = new Uint8Array(n);
            while (n--) {
                u8arr[n] = bstr.charCodeAt(n);
            }
            return new File([u8arr], name, { type: mime });
        }
        catch (_a) {
            return null;
        }
    };
    /**
     * @param {?} file
     * @return {?}
     */
    FileLoader.prototype.asDataUrl = /**
     * @param {?} file
     * @return {?}
     */
    function (file) {
        return this.read(file, 'dataurl');
    };
    /**
     * @param {?} file
     * @return {?}
     */
    FileLoader.prototype.asArrayBuffer = /**
     * @param {?} file
     * @return {?}
     */
    function (file) {
        return this.read(file, 'arraybuffer');
    };
    /**
     * @private
     * @template T
     * @param {?} file
     * @param {?} type
     * @return {?}
     */
    FileLoader.prototype.read = /**
     * @private
     * @template T
     * @param {?} file
     * @param {?} type
     * @return {?}
     */
    function (file, type) {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                return [2 /*return*/, new Promise((/**
                     * @param {?} resolve
                     * @param {?} reject
                     * @return {?}
                     */
                    function (resolve, reject) {
                        if (!file || !(file instanceof File)) {
                            return reject('Invalid file');
                        }
                        /** @type {?} */
                        var reader = new FileReader();
                        reader.onerror = (/**
                         * @return {?}
                         */
                        function () { return reject('Error file read'); });
                        reader.onabort = (/**
                         * @return {?}
                         */
                        function () { return reject('Abort file read'); });
                        reader.onload = (/**
                         * @return {?}
                         */
                        function () {
                            /** @type {?} */
                            var result = (/** @type {?} */ (reader.result));
                            return resolve((/** @type {?} */ (result)));
                        });
                        if (type === 'dataurl') {
                            reader.readAsDataURL(file);
                        }
                        else if (type === 'arraybuffer') {
                            reader.readAsArrayBuffer(file);
                        }
                    }))];
            });
        });
    };
    FileLoader.decorators = [
        { type: Injectable, args: [{
                    providedIn: 'root'
                },] }
    ];
    /** @nocollapse */ FileLoader.ngInjectableDef = ɵɵdefineInjectable({ factory: function FileLoader_Factory() { return new FileLoader(); }, token: FileLoader, providedIn: "root" });
    return FileLoader;
}());

/**
 * @fileoverview added by tsickle
 * Generated from: lib/core/services/languages.service.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
var Languages = /** @class */ (function () {
    function Languages() {
        this.getLanguages = (/**
         * @return {?}
         */
        function () {
            if (typeof navigator !== 'object') {
                return null;
            }
            /** @type {?} */
            var t = 'anguage';
            /** @type {?} */
            var n = navigator;
            /** @type {?} */
            var f = n['l' + t + 's'];
            /** @type {?} */
            var data = f && f.length ? f : (t = n['l' + t] ||
                n['browserL' + t] ||
                n['userL' + t]) ? [t] : t;
            return typeof data === 'string'
                ? data
                : data.join(';');
        });
    }
    Object.defineProperty(Languages.prototype, "all", {
        get: /**
         * @return {?}
         */
        function () {
            // Get the languages.
            /** @type {?} */
            var data = this.getLanguages();
            // Parse all languages by using a regex.
            /** @type {?} */
            var strings = (data || '')
                .match(/((([a-zA-Z]+(-[a-zA-Z0-9]+){0,2})|\*)(;q=[0-1](\.[0-9]+)?)?)*/g);
            // Get the content by parsing the strings.
            /** @type {?} */
            var content = strings.map((/**
             * @param {?} item
             * @return {?}
             */
            function (item) {
                if (!item) {
                    return null;
                }
                /** @type {?} */
                var bits = item.split(';');
                /** @type {?} */
                var ietf = bits[0].split('-');
                /** @type {?} */
                var hasScript = ietf.length === 3;
                return {
                    code: ietf[0],
                    script: hasScript ? ietf[1] : null,
                    region: hasScript ? ietf[2] : ietf[1],
                    quality: bits[1] ? parseFloat(bits[1].split('=')[1]) : 1.0
                };
            }));
            // Filter out all the empty items
            // and sort them by the quality.
            return content
                .filter((/**
             * @param {?} item
             * @return {?}
             */
            function (item) { return !!item; }))
                .sort((/**
             * @param {?} a
             * @param {?} b
             * @return {?}
             */
            function (a, b) { return b.quality - a.quality; }));
        },
        enumerable: true,
        configurable: true
    });
    Languages.decorators = [
        { type: Injectable, args: [{
                    providedIn: 'root'
                },] }
    ];
    /** @nocollapse */ Languages.ngInjectableDef = ɵɵdefineInjectable({ factory: function Languages_Factory() { return new Languages(); }, token: Languages, providedIn: "root" });
    return Languages;
}());
if (false) {
    /**
     * @type {?}
     * @private
     */
    Languages.prototype.getLanguages;
}

/**
 * @fileoverview added by tsickle
 * Generated from: lib/core/services/network.service.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
var Network = /** @class */ (function () {
    function Network(_platform) {
        this._platform = _platform;
        // Data.
        this._online$ = of(true);
        this.getOnlineObservable();
    }
    /**
     * @return {?}
     */
    Network.prototype.online = /**
     * @return {?}
     */
    function () {
        return this._online$;
    };
    /**
     * @private
     * @return {?}
     */
    Network.prototype.getOnlineObservable = /**
     * @private
     * @return {?}
     */
    function () {
        // Validate we are on a browser.
        if (!this._platform.isBrowser) {
            return;
        }
        // Get all the events from the window.
        /** @type {?} */
        var online$ = fromEvent(window, 'online').pipe(mapTo(true));
        /** @type {?} */
        var offline$ = fromEvent(window, 'offline').pipe(mapTo(false));
        /** @type {?} */
        var now$ = new Observable((/**
         * @param {?} subscriber
         * @return {?}
         */
        function (subscriber) {
            subscriber.next(navigator.onLine);
            subscriber.complete();
        }));
        // Merge all event so we get notified when
        // a user is online/offline.
        this._online$ = merge(now$, online$, offline$).pipe(map((/**
         * @param {?} value
         * @return {?}
         */
        function (value) { return (/** @type {?} */ (value)); })), distinctUntilChanged(), shareReplay(1));
    };
    Network.decorators = [
        { type: Injectable, args: [{
                    providedIn: 'root'
                },] }
    ];
    /** @nocollapse */
    Network.ctorParameters = function () { return [
        { type: Platform }
    ]; };
    /** @nocollapse */ Network.ngInjectableDef = ɵɵdefineInjectable({ factory: function Network_Factory() { return new Network(ɵɵinject(Platform)); }, token: Network, providedIn: "root" });
    return Network;
}());
if (false) {
    /**
     * @type {?}
     * @private
     */
    Network.prototype._online$;
    /**
     * @type {?}
     * @private
     */
    Network.prototype._platform;
}

/**
 * @fileoverview added by tsickle
 * Generated from: lib/core/services/patch.service.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
var Patch = /** @class */ (function () {
    function Patch(_platform) {
        this._platform = _platform;
        this._hasPatchedMobileVerticalHeight = false;
        // Subscriptions.
        this._subscriptions = [];
    }
    /**
     * @return {?}
     */
    Patch.prototype.mobileVerticalHeight = /**
     * @return {?}
     */
    function () {
        // Check if the user has already patched
        // the mobile vertical height.
        if (this._hasPatchedMobileVerticalHeight) {
            return;
        }
        this.periodicallySetDocumentVerticalProperty();
        this._hasPatchedMobileVerticalHeight = true;
    };
    /**
     * @return {?}
     */
    Patch.prototype.ngOnDestroy = /**
     * @return {?}
     */
    function () {
        this._subscriptions.forEach((/**
         * @param {?} subscription
         * @return {?}
         */
        function (subscription) { return subscription.unsubscribe(); }));
    };
    /**
     * @private
     * @return {?}
     */
    Patch.prototype.periodicallySetDocumentVerticalProperty = /**
     * @private
     * @return {?}
     */
    function () {
        // Validate we are using a browser.
        if (!this._platform.isBrowser) {
            return;
        }
        // Listen to a debounced window resize event.
        /** @type {?} */
        var resize$ = fromEvent(window, 'resize').pipe(debounceTime(25), startWith(0));
        // Subscribe to the resize observable.
        /** @type {?} */
        var subscription = resize$.subscribe((/**
         * @return {?}
         */
        function () {
            /** @type {?} */
            var verticalHeight = window.innerHeight * 0.01;
            /** @type {?} */
            var element = document.documentElement;
            if (!element.style) {
                return;
            }
            if (!element.style.setProperty) {
                return;
            }
            document.documentElement.style.setProperty('--vh', verticalHeight + "px");
        }));
        // Save the subscription so we can destroy it later.
        this._subscriptions.push(subscription);
    };
    Patch.decorators = [
        { type: Injectable, args: [{
                    providedIn: 'root'
                },] }
    ];
    /** @nocollapse */
    Patch.ctorParameters = function () { return [
        { type: Platform }
    ]; };
    /** @nocollapse */ Patch.ngInjectableDef = ɵɵdefineInjectable({ factory: function Patch_Factory() { return new Patch(ɵɵinject(Platform)); }, token: Patch, providedIn: "root" });
    return Patch;
}());
if (false) {
    /**
     * @type {?}
     * @private
     */
    Patch.prototype._hasPatchedMobileVerticalHeight;
    /**
     * @type {?}
     * @private
     */
    Patch.prototype._subscriptions;
    /**
     * @type {?}
     * @private
     */
    Patch.prototype._platform;
}

/**
 * @fileoverview added by tsickle
 * Generated from: lib/core/services/exif.service.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
var Exif = /** @class */ (function () {
    function Exif(_platform, _fileLoader) {
        this._platform = _platform;
        this._fileLoader = _fileLoader;
        this.transformImage = (/**
         * @param {?} image
         * @param {?} type
         * @param {?} orientation
         * @param {?=} quality
         * @return {?}
         */
        function (image, type, orientation, quality) {
            if (quality === void 0) { quality = 100; }
            // Create the canvas and context.
            /** @type {?} */
            var canvas = document.createElement('canvas');
            /** @type {?} */
            var context = canvas.getContext('2d');
            // Set the canvas size based on the image.
            var width = image.width, height = image.height;
            canvas.width = width;
            canvas.height = height;
            // Validate the orientation is correct
            // else flip the canvas sizes.
            if (4 < orientation && orientation < 9) {
                canvas.width = height;
                canvas.height = width;
            }
            // Transform the context based on the orientation.
            switch (orientation) {
                case 2:
                    context.transform(-1, 0, 0, 1, width, 0);
                    break;
                case 3:
                    context.transform(-1, 0, 0, -1, width, height);
                    break;
                case 4:
                    context.transform(1, 0, 0, -1, 0, height);
                    break;
                case 5:
                    context.transform(0, 1, 1, 0, 0, 0);
                    break;
                case 6:
                    context.transform(0, 1, -1, 0, height, 0);
                    break;
                case 7:
                    context.transform(0, -1, -1, 0, height, width);
                    break;
                case 8:
                    context.transform(0, -1, 1, 0, 0, width);
                    break;
                default:
                    break;
            }
            // Draw the image on the context and return the data URL.
            context.drawImage(image, 0, 0, width, height);
            return canvas.toDataURL(type, quality / 100);
        });
        this.getSupportedCanvasType = (/**
         * @param {?} fileType
         * @return {?}
         */
        function (fileType) {
            switch (fileType) {
                case 'image/jpeg':
                case 'image/jpg':
                    return 'image/jpeg';
                case 'image/x-windows-bmp':
                case 'image/bmp':
                    return 'image/bmp';
                default:
                    return 'image/png';
            }
        });
        this.getOrientation = (/**
         * @param {?} buffer
         * @return {?}
         */
        function (buffer) {
            // Create a new data view.
            /** @type {?} */
            var view = new DataView(buffer);
            if (view.getUint16(0, false) !== 0xFFD8) {
                return -2;
            }
            /** @type {?} */
            var length = view.byteLength;
            /** @type {?} */
            var offset = 2;
            while (offset < length) {
                if (view.getUint16(offset + 2, false) <= 8) {
                    return -1;
                }
                /** @type {?} */
                var marker = view.getUint16(offset, false);
                offset += 2;
                if (marker === 0xFFE1) {
                    if (view.getUint32(offset += 2, false) !== 0x45786966) {
                        return -1;
                    }
                    /** @type {?} */
                    var little = view.getUint16(offset += 6, false) === 0x4949;
                    offset += view.getUint32(offset + 4, little);
                    /** @type {?} */
                    var tags = view.getUint16(offset, little);
                    offset += 2;
                    for (var index = 0; index < tags; index++) {
                        if (view.getUint16(offset + index * 12, little) === 0x0112) {
                            return view.getUint16(offset + index * 12 + 8, little);
                        }
                    }
                }
                else if ((marker & 0xFF00) !== 0xFF00) {
                    break;
                }
                else {
                    offset += view.getUint16(offset, false);
                }
            }
            return -1;
        });
    }
    /**
     * @param {?} file
     * @param {?=} quality
     * @return {?}
     */
    Exif.prototype.strip = /**
     * @param {?} file
     * @param {?=} quality
     * @return {?}
     */
    function (file, quality) {
        if (quality === void 0) { quality = 100; }
        return __awaiter(this, void 0, void 0, function () {
            var arrayBuffer, dataUrl, imageElement, orientation_1, canvasType, imageUrl, _a;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        // Validate we are on a browser.
                        if (!this._platform.isBrowser) {
                            return [2 /*return*/, file];
                        }
                        // Validate the file exists and is
                        // an instance of a File object.
                        if (!file || !(file instanceof File)) {
                            return [2 /*return*/, file];
                        }
                        _b.label = 1;
                    case 1:
                        _b.trys.push([1, 5, , 6]);
                        // Read the file as an array buffer and data url.
                        return [4 /*yield*/, this._fileLoader.asArrayBuffer(file)];
                    case 2:
                        arrayBuffer = _b.sent();
                        return [4 /*yield*/, this._fileLoader.asDataUrl(file)];
                    case 3:
                        dataUrl = _b.sent();
                        // Create an image element.
                        return [4 /*yield*/, this.createImageElement(dataUrl)];
                    case 4:
                        imageElement = _b.sent();
                        // Get the orientation by using the buffer.
                        orientation_1 = this.getOrientation(arrayBuffer);
                        // Transform the image to remove the orientation.
                        canvasType = this.getSupportedCanvasType(file.type);
                        imageUrl = this.transformImage(imageElement, canvasType, orientation_1, quality);
                        // Transform the image url to a file.
                        return [2 /*return*/, this._fileLoader.toFile(imageUrl, file.name)];
                    case 5:
                        _a = _b.sent();
                        // When something goes wrong we
                        // just return the default file.
                        return [2 /*return*/, file];
                    case 6: return [2 /*return*/];
                }
            });
        });
    };
    /**
     * @private
     * @param {?} dataUrl
     * @return {?}
     */
    Exif.prototype.createImageElement = /**
     * @private
     * @param {?} dataUrl
     * @return {?}
     */
    function (dataUrl) {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                return [2 /*return*/, new Promise((/**
                     * @param {?} resolve
                     * @param {?} reject
                     * @return {?}
                     */
                    function (resolve, reject) {
                        /** @type {?} */
                        var image = new Image();
                        image.src = dataUrl;
                        image.onerror = (/**
                         * @return {?}
                         */
                        function () { return reject('Error image create'); });
                        image.onabort = (/**
                         * @return {?}
                         */
                        function () { return reject('Abort image create'); });
                        image.onload = (/**
                         * @return {?}
                         */
                        function () { return resolve(image); });
                    }))];
            });
        });
    };
    Exif.decorators = [
        { type: Injectable, args: [{
                    providedIn: 'root'
                },] }
    ];
    /** @nocollapse */
    Exif.ctorParameters = function () { return [
        { type: Platform },
        { type: FileLoader }
    ]; };
    /** @nocollapse */ Exif.ngInjectableDef = ɵɵdefineInjectable({ factory: function Exif_Factory() { return new Exif(ɵɵinject(Platform), ɵɵinject(FileLoader)); }, token: Exif, providedIn: "root" });
    return Exif;
}());
if (false) {
    /**
     * @type {?}
     * @private
     */
    Exif.prototype.transformImage;
    /**
     * @type {?}
     * @private
     */
    Exif.prototype.getSupportedCanvasType;
    /**
     * @type {?}
     * @private
     */
    Exif.prototype.getOrientation;
    /**
     * @type {?}
     * @private
     */
    Exif.prototype._platform;
    /**
     * @type {?}
     * @private
     */
    Exif.prototype._fileLoader;
}

/**
 * @fileoverview added by tsickle
 * Generated from: lib/core/mixins/constructor.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */

/**
 * @fileoverview added by tsickle
 * Generated from: lib/core/coercions/boolean-coercion.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
/**
 * @param {?} value
 * @return {?}
 */
function coerceBooleanProperty(value) {
    return value != null && "" + value !== 'false';
}

/**
 * @fileoverview added by tsickle
 * Generated from: lib/core/mixins/can-disable.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
/**
 * @record
 */
function CanDisable() { }
if (false) {
    /** @type {?} */
    CanDisable.prototype.disabled;
}
/**
 * @template T
 * @param {?} base
 * @return {?}
 */
function mixinDisabled(base) {
    return /** @class */ (function (_super) {
        __extends(class_1, _super);
        function class_1() {
            var args = [];
            for (var _i = 0; _i < arguments.length; _i++) {
                args[_i] = arguments[_i];
            }
            var _this = _super.apply(this, __spread(args)) || this;
            _this._disable = false;
            return _this;
        }
        Object.defineProperty(class_1.prototype, "disabled", {
            get: /**
             * @return {?}
             */
            function () {
                return this._disable;
            },
            set: /**
             * @param {?} value
             * @return {?}
             */
            function (value) {
                this._disable = coerceBooleanProperty(value);
            },
            enumerable: true,
            configurable: true
        });
        return class_1;
    }(base));
}

/**
 * @fileoverview added by tsickle
 * Generated from: lib/core/mixins/can-load.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
/**
 * @record
 */
function CanLoad() { }
if (false) {
    /** @type {?} */
    CanLoad.prototype.loading;
}
/**
 * @template T
 * @param {?} base
 * @return {?}
 */
function mixinLoad(base) {
    return /** @class */ (function (_super) {
        __extends(class_1, _super);
        function class_1() {
            var args = [];
            for (var _i = 0; _i < arguments.length; _i++) {
                args[_i] = arguments[_i];
            }
            var _this = _super.apply(this, __spread(args)) || this;
            _this._loading = false;
            return _this;
        }
        Object.defineProperty(class_1.prototype, "loading", {
            get: /**
             * @return {?}
             */
            function () {
                return this._loading;
            },
            set: /**
             * @param {?} value
             * @return {?}
             */
            function (value) {
                this._loading = coerceBooleanProperty(value);
            },
            enumerable: true,
            configurable: true
        });
        return class_1;
    }(base));
}

/**
 * @fileoverview added by tsickle
 * Generated from: lib/core/mixins/has-error.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
/**
 * @record
 */
function HasError() { }
if (false) {
    /** @type {?} */
    HasError.prototype.error;
}
/**
 * @template T
 * @param {?} base
 * @return {?}
 */
function mixinError(base) {
    return /** @class */ (function (_super) {
        __extends(class_1, _super);
        function class_1() {
            var args = [];
            for (var _i = 0; _i < arguments.length; _i++) {
                args[_i] = arguments[_i];
            }
            var _this = _super.apply(this, __spread(args)) || this;
            _this._error = false;
            return _this;
        }
        Object.defineProperty(class_1.prototype, "error", {
            get: /**
             * @return {?}
             */
            function () {
                return this._error;
            },
            set: /**
             * @param {?} value
             * @return {?}
             */
            function (value) {
                this._error = coerceBooleanProperty(value);
            },
            enumerable: true,
            configurable: true
        });
        return class_1;
    }(base));
}

/**
 * @fileoverview added by tsickle
 * Generated from: lib/core/mixins/can-hide-errors.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
/**
 * @record
 */
function CanHideErrors() { }
if (false) {
    /** @type {?} */
    CanHideErrors.prototype.hideErrors;
}
/**
 * @template T
 * @param {?} base
 * @return {?}
 */
function mixinHideErrors(base) {
    return /** @class */ (function (_super) {
        __extends(class_1, _super);
        function class_1() {
            var args = [];
            for (var _i = 0; _i < arguments.length; _i++) {
                args[_i] = arguments[_i];
            }
            var _this = _super.apply(this, __spread(args)) || this;
            _this._hideErrors = false;
            return _this;
        }
        Object.defineProperty(class_1.prototype, "hideErrors", {
            get: /**
             * @return {?}
             */
            function () {
                return this._hideErrors;
            },
            set: /**
             * @param {?} value
             * @return {?}
             */
            function (value) {
                this._hideErrors = coerceBooleanProperty(value);
            },
            enumerable: true,
            configurable: true
        });
        return class_1;
    }(base));
}

/**
 * @fileoverview added by tsickle
 * Generated from: lib/core/mixins/is-focused.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
/**
 * @record
 */
function IsFocused() { }
if (false) {
    /** @type {?} */
    IsFocused.prototype.focused;
}
/**
 * @template T
 * @param {?} base
 * @return {?}
 */
function mixinFocused(base) {
    return /** @class */ (function (_super) {
        __extends(class_1, _super);
        function class_1() {
            var args = [];
            for (var _i = 0; _i < arguments.length; _i++) {
                args[_i] = arguments[_i];
            }
            var _this = _super.apply(this, __spread(args)) || this;
            _this._focused = false;
            return _this;
        }
        Object.defineProperty(class_1.prototype, "focused", {
            get: /**
             * @return {?}
             */
            function () {
                return this._focused;
            },
            set: /**
             * @param {?} value
             * @return {?}
             */
            function (value) {
                this._focused = coerceBooleanProperty(value);
            },
            enumerable: true,
            configurable: true
        });
        return class_1;
    }(base));
}

/**
 * @fileoverview added by tsickle
 * Generated from: lib/core/mixins/is-grouped.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
/**
 * @record
 */
function IsGrouped() { }
if (false) {
    /** @type {?} */
    IsGrouped.prototype.grouped;
}
/**
 * @template T
 * @param {?} base
 * @return {?}
 */
function mixinGrouped(base) {
    return /** @class */ (function (_super) {
        __extends(class_1, _super);
        function class_1() {
            var args = [];
            for (var _i = 0; _i < arguments.length; _i++) {
                args[_i] = arguments[_i];
            }
            var _this = _super.apply(this, __spread(args)) || this;
            _this._grouped = false;
            return _this;
        }
        Object.defineProperty(class_1.prototype, "grouped", {
            get: /**
             * @return {?}
             */
            function () {
                return this._grouped;
            },
            set: /**
             * @param {?} value
             * @return {?}
             */
            function (value) {
                this._grouped = coerceBooleanProperty(value);
            },
            enumerable: true,
            configurable: true
        });
        return class_1;
    }(base));
}

/**
 * @fileoverview added by tsickle
 * Generated from: lib/core/mixins/is-readonly.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
/**
 * @record
 */
function IsReadonly() { }
if (false) {
    /** @type {?} */
    IsReadonly.prototype.readonly;
}
/**
 * @template T
 * @param {?} base
 * @return {?}
 */
function mixinReadonly(base) {
    return /** @class */ (function (_super) {
        __extends(class_1, _super);
        function class_1() {
            var args = [];
            for (var _i = 0; _i < arguments.length; _i++) {
                args[_i] = arguments[_i];
            }
            var _this = _super.apply(this, __spread(args)) || this;
            _this._readonly = false;
            return _this;
        }
        Object.defineProperty(class_1.prototype, "readonly", {
            get: /**
             * @return {?}
             */
            function () {
                return this._readonly;
            },
            set: /**
             * @param {?} value
             * @return {?}
             */
            function (value) {
                this._readonly = coerceBooleanProperty(value);
            },
            enumerable: true,
            configurable: true
        });
        return class_1;
    }(base));
}

/**
 * @fileoverview added by tsickle
 * Generated from: lib/core/mixins/is-required.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
/**
 * @record
 */
function IsRequired() { }
if (false) {
    /** @type {?} */
    IsRequired.prototype.required;
}
/**
 * @template T
 * @param {?} base
 * @return {?}
 */
function mixinRequired(base) {
    return /** @class */ (function (_super) {
        __extends(class_1, _super);
        function class_1() {
            var args = [];
            for (var _i = 0; _i < arguments.length; _i++) {
                args[_i] = arguments[_i];
            }
            var _this = _super.apply(this, __spread(args)) || this;
            _this._required = false;
            return _this;
        }
        Object.defineProperty(class_1.prototype, "required", {
            get: /**
             * @return {?}
             */
            function () {
                return this._required;
            },
            set: /**
             * @param {?} value
             * @return {?}
             */
            function (value) {
                this._required = coerceBooleanProperty(value);
            },
            enumerable: true,
            configurable: true
        });
        return class_1;
    }(base));
}

/**
 * @fileoverview added by tsickle
 * Generated from: lib/core/miscellaneous/regex.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
/** @type {?} */
var BbRegex = {
    email: /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
    fullNumber: /^\d*[1-9]\d*$/
};

/**
 * @fileoverview added by tsickle
 * Generated from: lib/core/miscellaneous/validator.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
var BbValidator = /** @class */ (function () {
    function BbValidator() {
    }
    /**
     * @param {?} control
     * @return {?}
     */
    BbValidator.email = /**
     * @param {?} control
     * @return {?}
     */
    function (control) {
        if (isEmptyInputValue(control.value)) {
            return null;
        }
        return BbRegex.email.test(control.value) ? null : { email: true };
    };
    /**
     * @param {?} control
     * @return {?}
     */
    BbValidator.fullNumber = /**
     * @param {?} control
     * @return {?}
     */
    function (control) {
        if (isEmptyInputValue(control.value)) {
            return null;
        }
        return BbRegex.fullNumber.test(control.value) ? null : { fullNumber: true };
    };
    /**
     * @param {?} bytes
     * @return {?}
     */
    BbValidator.maxFileSize = /**
     * @param {?} bytes
     * @return {?}
     */
    function (bytes) {
        /** @type {?} */
        var validator = (/**
         * @param {?} control
         * @return {?}
         */
        function (control) {
            /** @type {?} */
            var value = control.value;
            // Validate if the value is a file.
            if (!(value instanceof File)) {
                return null;
            }
            if (value.size <= bytes) {
                return null;
            }
            /** @type {?} */
            var maxSize = '0 Bytes';
            if (bytes !== 0) {
                /** @type {?} */
                var k = 1024;
                /** @type {?} */
                var dm = 2;
                /** @type {?} */
                var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
                /** @type {?} */
                var index = Math.floor(Math.log(bytes) / Math.log(k));
                maxSize = parseFloat((bytes / Math.pow(k, index)).toFixed(dm)) + ' ' + sizes[index];
            }
            return { maxFileSize: { maxSize: maxSize } };
        });
        return validator;
    };
    return BbValidator;
}());
/**
 * @param {?} value
 * @return {?}
 */
function isEmptyInputValue(value) {
    // We don't check for string here so it also works with arrays.
    return value == null || value.length === 0;
}

/**
 * @fileoverview added by tsickle
 * Generated from: public_api.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */

/**
 * @fileoverview added by tsickle
 * Generated from: bravobit-bb-foundation.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */

export { BbRegex, BbValidator, Exif, FileLoader, ImageConverter, Languages, Network, Patch, Platform, coerceBooleanProperty, mixinDisabled, mixinError, mixinFocused, mixinGrouped, mixinHideErrors, mixinLoad, mixinReadonly, mixinRequired };
//# sourceMappingURL=bravobit-bb-foundation.js.map
