import { Injectable, Optional, Inject, PLATFORM_ID, ɵɵdefineInjectable, ɵɵinject } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
import { __awaiter } 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 {?} */
const hasV8BreakIterator = (typeof Intl !== 'undefined' && ((/** @type {?} */ (Intl))).v8BreakIterator);
class Platform {
    /**
     * @param {?=} _platformId
     */
    constructor(_platformId) {
        this._platformId = _platformId;
    }
    // Browser check.
    /**
     * @return {?}
     */
    get isBrowser() {
        return this._platformId
            ? isPlatformBrowser(this._platformId)
            : typeof document === 'object' && !!document;
    }
    // Rendering engines.
    /**
     * @return {?}
     */
    get isTrident() {
        return this.isBrowser && /(msie|trident)/i.test(navigator.userAgent);
    }
    /**
     * @return {?}
     */
    get isBlink() {
        return this.isBrowser && (!!(((/** @type {?} */ (window))).chrome || hasV8BreakIterator) &&
            typeof CSS !== 'undefined' && !this.isEdge && !this.isTrident);
    }
    /**
     * @return {?}
     */
    get isWebkit() {
        return this.isBrowser && /AppleWebKit/i.test(navigator.userAgent)
            && !this.isBlink && !this.isEdge && !this.isTrident;
    }
    // Browsers.
    /**
     * @return {?}
     */
    get isChrome() {
        return this.isBrowser && /Google Inc./.test(navigator.vendor);
    }
    /**
     * @return {?}
     */
    get isEdge() {
        return this.isBrowser && /(edge)/i.test(navigator.userAgent);
    }
    /**
     * @return {?}
     */
    get isFirefox() {
        return this.isBrowser && /(firefox|minefield)/i.test(navigator.userAgent);
    }
    /**
     * @return {?}
     */
    get isSafari() {
        return this.isBrowser && /safari/i.test(navigator.userAgent) && this.isWebkit;
    }
    // Platforms.
    /**
     * @return {?}
     */
    get isIos() {
        return this.isBrowser && /iPad|iPhone|iPod/.test(navigator.userAgent) && !('MSStream' in window);
    }
    /**
     * @return {?}
     */
    get isAndroid() {
        return this.isBrowser && /android/i.test(navigator.userAgent) && !this.isTrident;
    }
    /**
     * @return {?}
     */
    get isDesktop() {
        return this.isBrowser && !(/(iPhone|iPod|iPad|Android|BlackBerry|IEMobile)/.test(navigator.userAgent));
    }
}
Platform.decorators = [
    { type: Injectable, args: [{
                providedIn: 'root'
            },] }
];
/** @nocollapse */
Platform.ctorParameters = () => [
    { 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" });
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
 */
class ImageConverter {
    /**
     * @param {?} _platform
     */
    constructor(_platform) {
        this._platform = _platform;
        // Data.
        this._types = ['image/png', 'image/jpeg'];
        this.calculateOffsetAndDimensions = (/**
         * @param {?} image
         * @param {?} canvasWidth
         * @param {?} canvasHeight
         * @return {?}
         */
        (image, canvasWidth, canvasHeight) => {
            /** @type {?} */
            const originalWidth = image.width;
            /** @type {?} */
            const originalHeight = image.height;
            /** @type {?} */
            const widthRatio = canvasWidth / originalWidth;
            /** @type {?} */
            const heightRatio = canvasHeight / originalHeight;
            /** @type {?} */
            let width = 0;
            /** @type {?} */
            let height = 0;
            if (originalWidth > originalHeight) {
                height = originalHeight * heightRatio;
                width = (originalWidth / originalHeight) * height;
            }
            else {
                width = originalWidth * widthRatio;
                height = (originalHeight / originalWidth) * width;
            }
            /** @type {?} */
            let xOffset = 0;
            /** @type {?} */
            let yOffset = 0;
            if (canvasHeight === height) {
                xOffset = -((width - canvasWidth) / 2);
            }
            else if (canvasWidth === width) {
                yOffset = -((height - canvasHeight) / 2);
            }
            return { xOffset, yOffset, width, height };
        });
    }
    /**
     * @param {?} contents
     * @param {?=} options
     * @return {?}
     */
    toDataUri(contents, options = null) {
        return __awaiter(this, void 0, void 0, function* () {
            // Check if the current platform is a browser.
            if (!this._platform.isBrowser) {
                return null;
            }
            // Get the image.
            /** @type {?} */
            const image = yield this.getImage(contents);
            // Get the canvas width and height.
            /** @type {?} */
            const canvasWidth = (options && options.width) || image.width;
            /** @type {?} */
            const canvasHeight = (options && options.height) || image.height;
            // Get the canvas and context.
            /** @type {?} */
            const canvas = document.createElement('canvas');
            /** @type {?} */
            const 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 canvas.toDataURL(this._types[0]);
            }
            // Get the dimensions and offsets.
            const { width, height, xOffset, yOffset } = this.calculateOffsetAndDimensions(image, canvasWidth, canvasHeight);
            // Draw the image.
            context.drawImage(image, 0, 0, image.width, image.height, xOffset, yOffset, width, height);
            // Convert the canvas to a data url.
            return canvas.toDataURL(this._types[0]);
        });
    }
    /**
     * @param {?} file
     * @param {?=} types
     * @return {?}
     */
    fileToImage(file, types = this._types) {
        return new Promise((/**
         * @param {?} resolve
         * @param {?} reject
         * @return {?}
         */
        (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 {?} */
            const fileReader = new FileReader();
            fileReader.readAsDataURL(file);
            fileReader.onloadend = (/**
             * @param {?} data
             * @return {?}
             */
            (data) => __awaiter(this, void 0, void 0, function* () {
                // Get the data URI.
                /** @type {?} */
                const dataUri = data.target['result'];
                // Convert the data URI to a image element.
                /** @type {?} */
                const image = yield this.stringToImage(dataUri);
                // Resolve the image.
                return resolve(image);
            }));
            fileReader.onerror = (/**
             * @param {?} error
             * @return {?}
             */
            error => reject(error));
        }));
    }
    /**
     * @param {?} src
     * @return {?}
     */
    stringToImage(src) {
        return new Promise((/**
         * @param {?} resolve
         * @param {?} reject
         * @return {?}
         */
        (resolve, reject) => {
            /** @type {?} */
            const image = new Image();
            image.src = src;
            image.onload = (/**
             * @return {?}
             */
            () => resolve(image));
            image.onerror = (/**
             * @param {?} error
             * @return {?}
             */
            error => reject(error));
        }));
    }
    /**
     * @private
     * @param {?} contents
     * @return {?}
     */
    getImage(contents) {
        return __awaiter(this, void 0, void 0, function* () {
            // If the contents is already an HTML image element just return it.
            if (contents instanceof HTMLImageElement) {
                return contents;
            }
            // If the contents is a file convert it to an HTML image element.
            if (contents instanceof File) {
                return this.fileToImage(contents);
            }
            // If the contents is a string convert it to an HTML image element.
            if (typeof contents === 'string') {
                return this.stringToImage(contents);
            }
        });
    }
}
ImageConverter.decorators = [
    { type: Injectable, args: [{
                providedIn: 'root'
            },] }
];
/** @nocollapse */
ImageConverter.ctorParameters = () => [
    { type: Platform }
];
/** @nocollapse */ ImageConverter.ngInjectableDef = ɵɵdefineInjectable({ factory: function ImageConverter_Factory() { return new ImageConverter(ɵɵinject(Platform)); }, token: ImageConverter, providedIn: "root" });
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
 */
class FileLoader {
    /**
     * @param {?} dataUri
     * @param {?=} name
     * @return {?}
     */
    toFile(dataUri, name = 'file') {
        try {
            /** @type {?} */
            const arr = dataUri.split(',');
            /** @type {?} */
            const mime = arr[0].match(/:(.*?);/)[1];
            /** @type {?} */
            const bstr = atob(arr[1]);
            /** @type {?} */
            let n = bstr.length;
            /** @type {?} */
            const 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 {?}
     */
    asDataUrl(file) {
        return this.read(file, 'dataurl');
    }
    /**
     * @param {?} file
     * @return {?}
     */
    asArrayBuffer(file) {
        return this.read(file, 'arraybuffer');
    }
    /**
     * @private
     * @template T
     * @param {?} file
     * @param {?} type
     * @return {?}
     */
    read(file, type) {
        return __awaiter(this, void 0, void 0, function* () {
            return new Promise((/**
             * @param {?} resolve
             * @param {?} reject
             * @return {?}
             */
            (resolve, reject) => {
                if (!file || !(file instanceof File)) {
                    return reject('Invalid file');
                }
                /** @type {?} */
                const reader = new FileReader();
                reader.onerror = (/**
                 * @return {?}
                 */
                () => reject('Error file read'));
                reader.onabort = (/**
                 * @return {?}
                 */
                () => reject('Abort file read'));
                reader.onload = (/**
                 * @return {?}
                 */
                () => {
                    /** @type {?} */
                    const 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" });

/**
 * @fileoverview added by tsickle
 * Generated from: lib/core/services/languages.service.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
class Languages {
    constructor() {
        this.getLanguages = (/**
         * @return {?}
         */
        () => {
            if (typeof navigator !== 'object') {
                return null;
            }
            /** @type {?} */
            let t = 'anguage';
            /** @type {?} */
            let n = navigator;
            /** @type {?} */
            let f = n['l' + t + 's'];
            /** @type {?} */
            const data = f && f.length ? f : (t = n['l' + t] ||
                n['browserL' + t] ||
                n['userL' + t]) ? [t] : t;
            return typeof data === 'string'
                ? data
                : data.join(';');
        });
    }
    /**
     * @return {?}
     */
    get all() {
        // Get the languages.
        /** @type {?} */
        const data = this.getLanguages();
        // Parse all languages by using a regex.
        /** @type {?} */
        const 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 {?} */
        const content = strings.map((/**
         * @param {?} item
         * @return {?}
         */
        item => {
            if (!item) {
                return null;
            }
            /** @type {?} */
            const bits = item.split(';');
            /** @type {?} */
            const ietf = bits[0].split('-');
            /** @type {?} */
            const 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 {?}
         */
        item => !!item))
            .sort((/**
         * @param {?} a
         * @param {?} b
         * @return {?}
         */
        (a, b) => b.quality - a.quality));
    }
}
Languages.decorators = [
    { type: Injectable, args: [{
                providedIn: 'root'
            },] }
];
/** @nocollapse */ Languages.ngInjectableDef = ɵɵdefineInjectable({ factory: function Languages_Factory() { return new Languages(); }, token: Languages, providedIn: "root" });
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
 */
class Network {
    /**
     * @param {?} _platform
     */
    constructor(_platform) {
        this._platform = _platform;
        // Data.
        this._online$ = of(true);
        this.getOnlineObservable();
    }
    /**
     * @return {?}
     */
    online() {
        return this._online$;
    }
    /**
     * @private
     * @return {?}
     */
    getOnlineObservable() {
        // Validate we are on a browser.
        if (!this._platform.isBrowser) {
            return;
        }
        // Get all the events from the window.
        /** @type {?} */
        const online$ = fromEvent(window, 'online').pipe(mapTo(true));
        /** @type {?} */
        const offline$ = fromEvent(window, 'offline').pipe(mapTo(false));
        /** @type {?} */
        const now$ = new Observable((/**
         * @param {?} subscriber
         * @return {?}
         */
        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 {?}
         */
        value => (/** @type {?} */ (value)))), distinctUntilChanged(), shareReplay(1));
    }
}
Network.decorators = [
    { type: Injectable, args: [{
                providedIn: 'root'
            },] }
];
/** @nocollapse */
Network.ctorParameters = () => [
    { type: Platform }
];
/** @nocollapse */ Network.ngInjectableDef = ɵɵdefineInjectable({ factory: function Network_Factory() { return new Network(ɵɵinject(Platform)); }, token: Network, providedIn: "root" });
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
 */
class Patch {
    /**
     * @param {?} _platform
     */
    constructor(_platform) {
        this._platform = _platform;
        this._hasPatchedMobileVerticalHeight = false;
        // Subscriptions.
        this._subscriptions = [];
    }
    /**
     * @return {?}
     */
    mobileVerticalHeight() {
        // Check if the user has already patched
        // the mobile vertical height.
        if (this._hasPatchedMobileVerticalHeight) {
            return;
        }
        this.periodicallySetDocumentVerticalProperty();
        this._hasPatchedMobileVerticalHeight = true;
    }
    /**
     * @return {?}
     */
    ngOnDestroy() {
        this._subscriptions.forEach((/**
         * @param {?} subscription
         * @return {?}
         */
        subscription => subscription.unsubscribe()));
    }
    /**
     * @private
     * @return {?}
     */
    periodicallySetDocumentVerticalProperty() {
        // Validate we are using a browser.
        if (!this._platform.isBrowser) {
            return;
        }
        // Listen to a debounced window resize event.
        /** @type {?} */
        const resize$ = fromEvent(window, 'resize').pipe(debounceTime(25), startWith(0));
        // Subscribe to the resize observable.
        /** @type {?} */
        const subscription = resize$.subscribe((/**
         * @return {?}
         */
        () => {
            /** @type {?} */
            const verticalHeight = window.innerHeight * 0.01;
            /** @type {?} */
            const 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 = () => [
    { type: Platform }
];
/** @nocollapse */ Patch.ngInjectableDef = ɵɵdefineInjectable({ factory: function Patch_Factory() { return new Patch(ɵɵinject(Platform)); }, token: Patch, providedIn: "root" });
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
 */
class Exif {
    /**
     * @param {?} _platform
     * @param {?} _fileLoader
     */
    constructor(_platform, _fileLoader) {
        this._platform = _platform;
        this._fileLoader = _fileLoader;
        this.transformImage = (/**
         * @param {?} image
         * @param {?} type
         * @param {?} orientation
         * @param {?=} quality
         * @return {?}
         */
        (image, type, orientation, quality = 100) => {
            // Create the canvas and context.
            /** @type {?} */
            const canvas = document.createElement('canvas');
            /** @type {?} */
            const context = canvas.getContext('2d');
            // Set the canvas size based on the image.
            const { width, height } = image;
            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 {?}
         */
        (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 {?}
         */
        (buffer) => {
            // Create a new data view.
            /** @type {?} */
            const view = new DataView(buffer);
            if (view.getUint16(0, false) !== 0xFFD8) {
                return -2;
            }
            /** @type {?} */
            const length = view.byteLength;
            /** @type {?} */
            let offset = 2;
            while (offset < length) {
                if (view.getUint16(offset + 2, false) <= 8) {
                    return -1;
                }
                /** @type {?} */
                const marker = view.getUint16(offset, false);
                offset += 2;
                if (marker === 0xFFE1) {
                    if (view.getUint32(offset += 2, false) !== 0x45786966) {
                        return -1;
                    }
                    /** @type {?} */
                    const little = view.getUint16(offset += 6, false) === 0x4949;
                    offset += view.getUint32(offset + 4, little);
                    /** @type {?} */
                    const tags = view.getUint16(offset, little);
                    offset += 2;
                    for (let 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 {?}
     */
    strip(file, quality = 100) {
        return __awaiter(this, void 0, void 0, function* () {
            // Validate we are on a browser.
            if (!this._platform.isBrowser) {
                return file;
            }
            // Validate the file exists and is
            // an instance of a File object.
            if (!file || !(file instanceof File)) {
                return file;
            }
            try {
                // Read the file as an array buffer and data url.
                /** @type {?} */
                const arrayBuffer = yield this._fileLoader.asArrayBuffer(file);
                /** @type {?} */
                const dataUrl = yield this._fileLoader.asDataUrl(file);
                // Create an image element.
                /** @type {?} */
                const imageElement = yield this.createImageElement(dataUrl);
                // Get the orientation by using the buffer.
                /** @type {?} */
                const orientation = this.getOrientation(arrayBuffer);
                // Transform the image to remove the orientation.
                /** @type {?} */
                const canvasType = this.getSupportedCanvasType(file.type);
                /** @type {?} */
                const imageUrl = this.transformImage(imageElement, canvasType, orientation, quality);
                // Transform the image url to a file.
                return this._fileLoader.toFile(imageUrl, file.name);
            }
            catch (_a) {
                // When something goes wrong we
                // just return the default file.
                return file;
            }
        });
    }
    /**
     * @private
     * @param {?} dataUrl
     * @return {?}
     */
    createImageElement(dataUrl) {
        return __awaiter(this, void 0, void 0, function* () {
            return new Promise((/**
             * @param {?} resolve
             * @param {?} reject
             * @return {?}
             */
            (resolve, reject) => {
                /** @type {?} */
                const image = new Image();
                image.src = dataUrl;
                image.onerror = (/**
                 * @return {?}
                 */
                () => reject('Error image create'));
                image.onabort = (/**
                 * @return {?}
                 */
                () => reject('Abort image create'));
                image.onload = (/**
                 * @return {?}
                 */
                () => resolve(image));
            }));
        });
    }
}
Exif.decorators = [
    { type: Injectable, args: [{
                providedIn: 'root'
            },] }
];
/** @nocollapse */
Exif.ctorParameters = () => [
    { type: Platform },
    { type: FileLoader }
];
/** @nocollapse */ Exif.ngInjectableDef = ɵɵdefineInjectable({ factory: function Exif_Factory() { return new Exif(ɵɵinject(Platform), ɵɵinject(FileLoader)); }, token: Exif, providedIn: "root" });
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 extends base {
        /**
         * @param {...?} args
         */
        constructor(...args) {
            super(...args);
            this._disable = false;
        }
        /**
         * @return {?}
         */
        get disabled() {
            return this._disable;
        }
        /**
         * @param {?} value
         * @return {?}
         */
        set disabled(value) {
            this._disable = coerceBooleanProperty(value);
        }
    };
}

/**
 * @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 extends base {
        /**
         * @param {...?} args
         */
        constructor(...args) {
            super(...args);
            this._loading = false;
        }
        /**
         * @return {?}
         */
        get loading() {
            return this._loading;
        }
        /**
         * @param {?} value
         * @return {?}
         */
        set loading(value) {
            this._loading = coerceBooleanProperty(value);
        }
    };
}

/**
 * @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 extends base {
        /**
         * @param {...?} args
         */
        constructor(...args) {
            super(...args);
            this._error = false;
        }
        /**
         * @return {?}
         */
        get error() {
            return this._error;
        }
        /**
         * @param {?} value
         * @return {?}
         */
        set error(value) {
            this._error = coerceBooleanProperty(value);
        }
    };
}

/**
 * @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 extends base {
        /**
         * @param {...?} args
         */
        constructor(...args) {
            super(...args);
            this._hideErrors = false;
        }
        /**
         * @return {?}
         */
        get hideErrors() {
            return this._hideErrors;
        }
        /**
         * @param {?} value
         * @return {?}
         */
        set hideErrors(value) {
            this._hideErrors = coerceBooleanProperty(value);
        }
    };
}

/**
 * @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 extends base {
        /**
         * @param {...?} args
         */
        constructor(...args) {
            super(...args);
            this._focused = false;
        }
        /**
         * @return {?}
         */
        get focused() {
            return this._focused;
        }
        /**
         * @param {?} value
         * @return {?}
         */
        set focused(value) {
            this._focused = coerceBooleanProperty(value);
        }
    };
}

/**
 * @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 extends base {
        /**
         * @param {...?} args
         */
        constructor(...args) {
            super(...args);
            this._grouped = false;
        }
        /**
         * @return {?}
         */
        get grouped() {
            return this._grouped;
        }
        /**
         * @param {?} value
         * @return {?}
         */
        set grouped(value) {
            this._grouped = coerceBooleanProperty(value);
        }
    };
}

/**
 * @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 extends base {
        /**
         * @param {...?} args
         */
        constructor(...args) {
            super(...args);
            this._readonly = false;
        }
        /**
         * @return {?}
         */
        get readonly() {
            return this._readonly;
        }
        /**
         * @param {?} value
         * @return {?}
         */
        set readonly(value) {
            this._readonly = coerceBooleanProperty(value);
        }
    };
}

/**
 * @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 extends base {
        /**
         * @param {...?} args
         */
        constructor(...args) {
            super(...args);
            this._required = false;
        }
        /**
         * @return {?}
         */
        get required() {
            return this._required;
        }
        /**
         * @param {?} value
         * @return {?}
         */
        set required(value) {
            this._required = coerceBooleanProperty(value);
        }
    };
}

/**
 * @fileoverview added by tsickle
 * Generated from: lib/core/miscellaneous/regex.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
/** @type {?} */
const 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
 */
class BbValidator {
    /**
     * @param {?} control
     * @return {?}
     */
    static email(control) {
        if (isEmptyInputValue(control.value)) {
            return null;
        }
        return BbRegex.email.test(control.value) ? null : { email: true };
    }
    /**
     * @param {?} control
     * @return {?}
     */
    static fullNumber(control) {
        if (isEmptyInputValue(control.value)) {
            return null;
        }
        return BbRegex.fullNumber.test(control.value) ? null : { fullNumber: true };
    }
    /**
     * @param {?} bytes
     * @return {?}
     */
    static maxFileSize(bytes) {
        /** @type {?} */
        const validator = (/**
         * @param {?} control
         * @return {?}
         */
        (control) => {
            /** @type {?} */
            const value = control.value;
            // Validate if the value is a file.
            if (!(value instanceof File)) {
                return null;
            }
            if (value.size <= bytes) {
                return null;
            }
            /** @type {?} */
            let maxSize = '0 Bytes';
            if (bytes !== 0) {
                /** @type {?} */
                const k = 1024;
                /** @type {?} */
                const dm = 2;
                /** @type {?} */
                const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
                /** @type {?} */
                const index = Math.floor(Math.log(bytes) / Math.log(k));
                maxSize = parseFloat((bytes / Math.pow(k, index)).toFixed(dm)) + ' ' + sizes[index];
            }
            return { maxFileSize: { maxSize } };
        });
        return validator;
    }
}
/**
 * @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
