import * as i2 from '@angular/common';
import { CommonModule } from '@angular/common';
import * as i0 from '@angular/core';
import { Component, Input, EventEmitter, Self, Optional, Output, NgModule } from '@angular/core';
import * as i1 from '@angular/forms';
import { FormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import * as i3 from '@angular/material/icon';
import { MatIconModule } from '@angular/material/icon';
import { Destroy } from '@deja-js/component/core';
import { takeUntil, combineLatestWith, map, BehaviorSubject, Subject, tap, distinctUntilChanged, debounce, timer, mergeWith, debounceTime, delay, filter, fromEvent, take } from 'rxjs';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { Color } from '@deja-js/component/core/graphics';

class DejaColorFabComponent extends Destroy {
    constructor(el) {
        super();
        this.element = el.nativeElement;
    }
    set color(colorFab) {
        this._colorFab = colorFab;
        if (colorFab) {
            const toggleAttribute = (attribute, value) => {
                if (value) {
                    this.element.setAttribute(attribute, value.toString());
                }
                else {
                    this.element.removeAttribute(attribute);
                }
            };
            colorFab.active$.pipe(takeUntil(this.destroyed$)).subscribe(value => toggleAttribute('active', value));
            colorFab.color$.pipe(combineLatestWith(colorFab.disabled$), map(([color, disabled]) => color && disabled ? color.grayScale : color), takeUntil(this.destroyed$)).subscribe(color => this.element.style.backgroundColor = color ? color.toHex() : '');
        }
    }
    get tile() {
        return this._colorFab;
    }
}
DejaColorFabComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: DejaColorFabComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
DejaColorFabComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.1.3", type: DejaColorFabComponent, selector: "deja-color-fab", inputs: { color: "color" }, usesInheritance: true, ngImport: i0, template: '<ng-content></ng-content>', isInline: true, styles: [":host{border-radius:50%;cursor:pointer;transition:all linear .2s;width:2.5rem;height:2.5rem;display:flex;align-items:center;justify-content:space-around;margin:.45rem}:host[small]{width:1.65rem;height:1.65rem;margin:.3rem}:host[active]{transform:scale(1.4);transition:transform linear .2s!important}\n"] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: DejaColorFabComponent, decorators: [{
            type: Component,
            args: [{ selector: 'deja-color-fab', template: '<ng-content></ng-content>', styles: [":host{border-radius:50%;cursor:pointer;transition:all linear .2s;width:2.5rem;height:2.5rem;display:flex;align-items:center;justify-content:space-around;margin:.45rem}:host[small]{width:1.65rem;height:1.65rem;margin:.3rem}:host[active]{transform:scale(1.4);transition:transform linear .2s!important}\n"] }]
        }], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { color: [{
                type: Input
            }] } });

/*
 *  @license
 *  Copyright Hôpitaux Universitaires de Genève. All Rights Reserved.
 *
 *  Use of this source code is governed by an Apache-2.0 license that can be
 *  found in the LICENSE file at https://github.com/DSI-HUG/dejajs-components/blob/master/LICENSE
 */
class DejaColorFab {
    // eslint-disable-next-line @typescript-eslint/naming-convention
    constructor(_color, _disabled = false, _active = false) {
        this._color = _color;
        this._disabled = _disabled;
        this._active = _active;
        this.color$ = new BehaviorSubject(_color);
        this.disabled$ = new BehaviorSubject(_disabled);
        this.active$ = new BehaviorSubject(_active);
    }
    set color(value) {
        this.color$.next(this._color = value);
    }
    get color() {
        return this._color;
    }
    set disabled(value) {
        this.disabled$.next(this._disabled = value);
    }
    get disabled() {
        return this._disabled;
    }
    set active(value) {
        this.active$.next(this._active = value);
    }
    get active() {
        return this._active;
    }
}

/*
 *  @license
 *  Copyright Hôpitaux Universitaires de Genève. All Rights Reserved.
 *
 *  Use of this source code is governed by an Apache-2.0 license that can be
 *  found in the LICENSE file at https://github.com/DSI-HUG/dejajs-components/blob/master/LICENSE
 */
/** Composant de selection d'une couleur. */
class DejaColorSelectorComponent {
    constructor(elementRef, control) {
        this.control = control;
        /** Evénement déclenché lorsqu'une couleur est survolée par la souris. */
        this.colorhover = new EventEmitter();
        this.destroyed$ = new Subject();
        this._colors$ = new BehaviorSubject([]);
        this._resetcolor$ = new BehaviorSubject(null);
        this._colorFabs = [];
        this._subColorFabs = [];
        this._selectedBaseIndex = 0;
        this._disabled = false;
        this.selectedBaseIndex$ = new BehaviorSubject(0);
        this.selectedSubIndex$ = new BehaviorSubject(0);
        this.hilightedBaseIndex$ = new Subject();
        this.hilightedSubIndex$ = new Subject();
        // ************* End of ControlValueAccessor Implementation **************
        // ngModel
        this.onTouchedCallback = () => undefined;
        this.onChangeCallback = (_a) => undefined;
        const element = elementRef.nativeElement;
        if (this.control) {
            this.control.valueAccessor = this;
        }
        this._colorFabs$ = this._colors$.pipe(map(colors => colors.map((color, index) => new DejaColorFab(color, this._disabled, index === this._selectedBaseIndex))), tap(colorFabs => this._colorFabs = colorFabs));
        this._colors$.pipe(combineLatestWith(this._resetcolor$), takeUntil(this.destroyed$)).subscribe(([colors, resetcolor]) => {
            if (!colors || !colors.length || !resetcolor) {
                this._resetcolor = undefined;
                return;
            }
            const allColors = colors.reduce((acc, color) => {
                const materialColor = color;
                if (materialColor.subColors) {
                    acc = [...acc, ...materialColor.subColors];
                }
                else {
                    acc.push(color);
                }
                return acc;
            }, []);
            let bestColor;
            allColors.reduce((bestDiff, color) => {
                // The best formula we found for our eye
                const diff = 0.3 * Math.abs(color.r - resetcolor.r) + 0.4 * Math.abs(color.g - resetcolor.g) + 0.25 * Math.abs(color.b - resetcolor.b);
                if (diff < bestDiff) {
                    bestColor = color;
                    return diff;
                }
                return bestDiff;
            }, 3 * 255);
            this._resetcolor = bestColor;
        });
        const hilightedBaseIndex$ = this.hilightedBaseIndex$.pipe(distinctUntilChanged(), debounce(colorIndex => timer(colorIndex !== undefined ? 100 : 1000)), tap(colorIndex => {
            var _b, _c;
            this.hilightedBaseIndex = colorIndex;
            const event = new CustomEvent('ColorEvent', {});
            event.color = colorIndex ? (_c = (_b = this._colorFabs) === null || _b === void 0 ? void 0 : _b[colorIndex]) === null || _c === void 0 ? void 0 : _c.color : this.value;
            this.colorhover.emit(event);
        }), map(colorIndex => colorIndex !== undefined ? colorIndex : this._selectedBaseIndex || 0));
        const selectedBaseIndex$ = this.selectedBaseIndex$.pipe(tap(colorIndex => this._selectedBaseIndex = colorIndex));
        this._subColorFabs$ = hilightedBaseIndex$.pipe(mergeWith(selectedBaseIndex$), distinctUntilChanged(), tap(colorIndex => {
            if (this._colorFabs) {
                this._colorFabs.forEach((colorFab, index) => colorFab.active = index === colorIndex);
            }
        }), debounceTime(100), tap(() => element.setAttribute('sub-tr', '')), map(baseIndex => { var _b; return ((_b = this._colorFabs) === null || _b === void 0 ? void 0 : _b[baseIndex]) && this._colorFabs[baseIndex].color.subColors; }), map(colors => colors === null || colors === void 0 ? void 0 : colors.map((color, index) => new DejaColorFab(color, this._disabled, index === this._selectedSubIndex))), tap(subColorFabs => this._subColorFabs = subColorFabs));
        this._subColorFabs$.pipe(delay(100), takeUntil(this.destroyed$)).subscribe(() => element.removeAttribute('sub-tr'));
        const hilightedSubIndex$ = this.hilightedSubIndex$.pipe(distinctUntilChanged(), debounce(subColorIndex => timer(subColorIndex !== undefined ? 200 : 1100)), tap(subColorIndex => {
            var _b, _c;
            this.hilightedSubIndex = subColorIndex;
            const event = new CustomEvent('ColorEvent', {});
            event.color = subColorIndex !== undefined ? (_c = (_b = this._subColorFabs) === null || _b === void 0 ? void 0 : _b[subColorIndex]) === null || _c === void 0 ? void 0 : _c.color : this.value;
            this.colorhover.emit(event);
        }), map(subColorIndex => subColorIndex !== undefined ? subColorIndex : this._selectedSubIndex || 0));
        const selectedSubIndex$ = this.selectedSubIndex$.pipe(distinctUntilChanged(), tap(subColorIndex => this._selectedSubIndex = subColorIndex));
        hilightedSubIndex$.pipe(mergeWith(selectedSubIndex$), filter(() => !!this._subColorFabs), takeUntil(this.destroyed$)).subscribe(subColorIndex => this._subColorFabs.forEach((colorFab, index) => colorFab.active = index === subColorIndex));
        fromEvent(element, 'mousemove').pipe(filter(() => !this._disabled), takeUntil(this.destroyed$)).subscribe(event => {
            const target = event.target;
            // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
            const targetIndex = target.attributes[DejaColorSelectorComponent.INDEX_ATTRIBUTE];
            if (target.hasAttribute('basecolor')) {
                // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
                this.hilightedBaseIndex$.next(+targetIndex.value);
                this.hilightedSubIndex$.next(this.hilightedSubIndex);
            }
            else if (target.hasAttribute('subcolor')) {
                this.hilightedBaseIndex$.next(this.hilightedBaseIndex);
                // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
                this.hilightedSubIndex$.next(+targetIndex.value);
            }
            else {
                this.hilightedBaseIndex$.next(undefined);
                this.hilightedSubIndex$.next(undefined);
            }
        });
        fromEvent(element, 'click').pipe(filter(() => !this._disabled), takeUntil(this.destroyed$)).subscribe(event => {
            const target = event.target;
            if (target.hasAttribute('basecolor') || target.hasAttribute('subcolor')) {
                this.value = Color.parse(target.style.backgroundColor);
            }
        });
    }
    get subColorFabs() {
        return this._subColorFabs;
    }
    get subColorFabs$() {
        return this._subColorFabs$;
    }
    get colorFabs$() {
        return this._colorFabs$;
    }
    set resetcolor(value) {
        if (value === '') {
            value = new Color();
        }
        const color = value && (typeof value === 'string' ? Color.parse(value) : value);
        this._resetcolor$.next(color || null);
    }
    /** Retourne ou definit si le selecteur est desactivé. */
    set disabled(value) {
        const disabled = coerceBooleanProperty(value);
        if (this._colorFabs) {
            this._colorFabs.forEach(colorFab => colorFab.disabled = disabled);
        }
        if (this._subColorFabs) {
            this._subColorFabs.forEach(colorFab => colorFab.disabled = disabled);
        }
        this._disabled = disabled || null;
    }
    get disabled() {
        return this._disabled;
    }
    /**
     * Retourne la meilleure couleur d'affichage pour une couleur donnée
     */
    getBestTextColor(value) {
        const backColor = Color.fromHex(value);
        return backColor.bestTextColor.toHex();
    }
    resetDefaultColor() {
        this.value = this._resetcolor;
    }
    /**
     * Definit les couleurs selectionables affichées.
     *
     * @param colors Structure hierarchique des couleurs selectionablea suivant le modele MaterialColor.
     */
    set colors(colors) {
        this._colors$.next(colors || []);
        this.selectedBaseIndex$.next(0);
    }
    set selectedColor(color) {
        const selectSubIndex = (index) => {
            timer(1).pipe(take(1), takeUntil(this.destroyed$)).subscribe(() => this.selectedSubIndex$.next(index));
        };
        if (this._colorFabs) {
            const find = this._colorFabs.find((colorFab, index) => {
                var _b;
                const baseColor = colorFab.color;
                const subIndex = (_b = baseColor.subColors) === null || _b === void 0 ? void 0 : _b.findIndex(subColor => Color.equals(subColor, color));
                if (subIndex !== undefined && subIndex >= 0) {
                    this.selectedBaseIndex$.next(index);
                    selectSubIndex(subIndex);
                    // Break
                    return true;
                }
                else if (Color.equals(baseColor, color)) {
                    this.selectedBaseIndex$.next(index);
                    selectSubIndex(0);
                    // Break
                    return true;
                }
                // Continue
                return false;
            });
            if (!find) {
                this.selectedBaseIndex$.next(0);
                selectSubIndex(0);
            }
        }
    }
    // ************* ControlValueAccessor Implementation **************
    // set accessor including call the onchange callback
    set value(value) {
        if (!Color.equals(value, this._value)) {
            this.writeValue(value);
            this.onChangeCallback(value);
        }
    }
    // get accessor
    get value() {
        return this._value;
    }
    // From ControlValueAccessor interface
    writeValue(value) {
        this._value = value;
        this.selectedColor = value;
    }
    // From ControlValueAccessor interface
    registerOnChange(fn) {
        this.onChangeCallback = fn;
    }
    // From ControlValueAccessor interface
    registerOnTouched(fn) {
        this.onTouchedCallback = fn;
    }
    setDisabledState(isDisabled) {
        this.disabled = isDisabled;
    }
    ngOnDestroy() {
        this.destroyed$.next();
        this.destroyed$.unsubscribe();
    }
}
DejaColorSelectorComponent.INDEX_ATTRIBUTE = 'index';
DejaColorSelectorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: DejaColorSelectorComponent, deps: [{ token: i0.ElementRef }, { token: i1.NgControl, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Component });
DejaColorSelectorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.1.3", type: DejaColorSelectorComponent, selector: "deja-color-selector", inputs: { resetcolor: "resetcolor", disabled: "disabled", colors: "colors" }, outputs: { colorhover: "colorhover" }, ngImport: i0, template: "<div class=\"colors-wrapper\" id=\"basecolors\">\n\t<deja-color-fab basecolor small *ngFor=\"let clrfab of colorFabs$ | async; let index=index\" [attr.index]=\"index\" [color]=\"clrfab\"></deja-color-fab>\n</div>\n<div class=\"colors-wrapper\" id=\"subcolors\">\n\t<deja-color-fab subcolor *ngFor=\"let clrfab of subColorFabs$ | async; let index=index\" [attr.index]=\"index\" [style.transition-duration]=\"(100*index)+'ms'\" [color]=\"clrfab\"></deja-color-fab>\n</div>\n<div id=\"reset\" *ngIf=\"!!_resetcolor\" (click)=\"resetDefaultColor()\" [style.background-color]=\"_resetcolor.toHex()\">\n\t<mat-icon [style.color]=\"getBestTextColor(_resetcolor.toHex())\">undo</mat-icon>\n</div>", styles: [":host{display:flex;flex-direction:column}:host .colors-wrapper{display:flex;flex-direction:row;align-items:center;justify-content:center;flex-wrap:wrap;margin:1rem .5rem}:host .colors-wrapper deja-color-fab{float:left}:host .colors-wrapper #subcolors deja-color-fab{opacity:1}:host[sub-tr] #subcolors.colors-wrapper deja-color-fab{opacity:0;transform:scale(0)}:host #reset{padding:.5rem 0;cursor:pointer;text-align:center}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: DejaColorFabComponent, selector: "deja-color-fab", inputs: ["color"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: DejaColorSelectorComponent, decorators: [{
            type: Component,
            args: [{ selector: 'deja-color-selector', template: "<div class=\"colors-wrapper\" id=\"basecolors\">\n\t<deja-color-fab basecolor small *ngFor=\"let clrfab of colorFabs$ | async; let index=index\" [attr.index]=\"index\" [color]=\"clrfab\"></deja-color-fab>\n</div>\n<div class=\"colors-wrapper\" id=\"subcolors\">\n\t<deja-color-fab subcolor *ngFor=\"let clrfab of subColorFabs$ | async; let index=index\" [attr.index]=\"index\" [style.transition-duration]=\"(100*index)+'ms'\" [color]=\"clrfab\"></deja-color-fab>\n</div>\n<div id=\"reset\" *ngIf=\"!!_resetcolor\" (click)=\"resetDefaultColor()\" [style.background-color]=\"_resetcolor.toHex()\">\n\t<mat-icon [style.color]=\"getBestTextColor(_resetcolor.toHex())\">undo</mat-icon>\n</div>", styles: [":host{display:flex;flex-direction:column}:host .colors-wrapper{display:flex;flex-direction:row;align-items:center;justify-content:center;flex-wrap:wrap;margin:1rem .5rem}:host .colors-wrapper deja-color-fab{float:left}:host .colors-wrapper #subcolors deja-color-fab{opacity:1}:host[sub-tr] #subcolors.colors-wrapper deja-color-fab{opacity:0;transform:scale(0)}:host #reset{padding:.5rem 0;cursor:pointer;text-align:center}\n"] }]
        }], ctorParameters: function () {
        return [{ type: i0.ElementRef }, { type: i1.NgControl, decorators: [{
                        type: Self
                    }, {
                        type: Optional
                    }] }];
    }, propDecorators: { colorhover: [{
                type: Output
            }], resetcolor: [{
                type: Input
            }], disabled: [{
                type: Input
            }], colors: [{
                type: Input
            }] } });

/*
 *  @license
 *  Copyright Hôpitaux Universitaires de Genève. All Rights Reserved.
 *
 *  Use of this source code is governed by an Apache-2.0 license that can be
 *  found in the LICENSE file at https://github.com/DSI-HUG/dejajs-components/blob/master/LICENSE
 */
class DejaColorSelectorModule {
}
DejaColorSelectorModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: DejaColorSelectorModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
DejaColorSelectorModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.1.3", ngImport: i0, type: DejaColorSelectorModule, declarations: [DejaColorFabComponent, DejaColorSelectorComponent], imports: [CommonModule,
        FormsModule,
        MatButtonModule,
        MatIconModule], exports: [DejaColorFabComponent, DejaColorSelectorComponent] });
DejaColorSelectorModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: DejaColorSelectorModule, imports: [CommonModule,
        FormsModule,
        MatButtonModule,
        MatIconModule] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: DejaColorSelectorModule, decorators: [{
            type: NgModule,
            args: [{
                    declarations: [DejaColorFabComponent, DejaColorSelectorComponent],
                    exports: [DejaColorFabComponent, DejaColorSelectorComponent],
                    imports: [
                        CommonModule,
                        FormsModule,
                        MatButtonModule,
                        MatIconModule
                    ]
                }]
        }] });

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

export { DejaColorFab, DejaColorFabComponent, DejaColorSelectorComponent, DejaColorSelectorModule };
//# sourceMappingURL=deja-js-component-color-selector.mjs.map
