// Copyright Project Harbor Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import {
    AfterViewInit,
    ChangeDetectionStrategy,
    Component,
    DoCheck,
    ElementRef,
    Input,
    OnInit,
    ViewChild,
} from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { forkJoin } from 'rxjs';

@Component({
    selector: 'histogram-chart',
    templateUrl: './histogram-chart.component.html',
    styleUrls: ['./histogram-chart.component.scss'],
    changeDetection: ChangeDetectionStrategy.OnPush,
})
export class HistogramChartComponent implements OnInit, AfterViewInit, DoCheck {
    @Input()
    metadata: Array<{
        text: string;
        value: number;
        color: string;
    }> = [];
    translatedTextArr: Array<string> = [];
    @Input()
    isWhiteBackground: boolean = false;
    max: number;
    scale: number;
    hasViewInit: boolean = false;
    @ViewChild('barChart') barChart: ElementRef;
    public context: CanvasRenderingContext2D;
    constructor(private translate: TranslateService) {}

    ngOnInit() {
        this.translateText();
    }
    ngAfterViewInit(): void {
        this.hasViewInit = true;
        this.initChart();
    }
    ngDoCheck() {
        if (this.hasViewInit) {
            this.initChart();
        }
    }
    translateText() {
        if (this.metadata && this.metadata.length > 0) {
            let textArr = [];
            this.metadata.forEach(item => {
                textArr.push(this.translate.get(item.text));
            });
            forkJoin(textArr).subscribe((res: string[]) => {
                this.translatedTextArr = res;
                if (this.hasViewInit) {
                    this.initChart();
                }
            });
        }
    }
    initChart() {
        if (this.barChart && this.metadata && this.metadata.length > 0) {
            this.barChart.nativeElement.width = '240';
            this.barChart.nativeElement.height =
                25 + 20 * this.metadata.length + '';
            this.context = this.barChart.nativeElement.getContext('2d');
            this.getMax();
            if (this.isWhiteBackground) {
                this.context.fillStyle = '#000';
            } else {
                this.context.fillStyle = '#fff';
            }
            this.drawLine(50, 0, 50, 5 + this.metadata.length * 20);
            this.drawLine(
                50,
                5 + this.metadata.length * 20,
                250,
                5 + this.metadata.length * 20
            );
            this.drawLine(
                90,
                5 + this.metadata.length * 20,
                90,
                2 + this.metadata.length * 20
            );
            this.drawLine(
                130,
                5 + this.metadata.length * 20,
                130,
                2 + this.metadata.length * 20
            );
            this.drawLine(
                170,
                5 + this.metadata.length * 20,
                170,
                2 + this.metadata.length * 20
            );
            this.drawLine(
                210,
                5 + this.metadata.length * 20,
                210,
                2 + this.metadata.length * 20
            );
            this.context.font = '12px';
            this.context.textAlign = 'center';
            this.context.fillText(
                this.scale.toString(),
                90,
                this.metadata.length * 20 + 18,
                50
            );
            this.context.fillText(
                (2 * this.scale).toString(),
                130,
                this.metadata.length * 20 + 18,
                50
            );
            this.context.fillText(
                (3 * this.scale).toString(),
                170,
                this.metadata.length * 20 + 18,
                50
            );
            this.context.fillText(
                (4 * this.scale).toString(),
                210,
                this.metadata.length * 20 + 18,
                50
            );
            this.metadata.forEach((item, index) => {
                this.drawBar(index, item.color, item.value);
            });
        }
    }
    drawBar(index: number, color: string, value: number) {
        this.context.textBaseline = 'middle';
        this.context.textAlign = 'left';
        this.context.fillStyle = color;
        this.context.fillRect(
            50,
            5 + index * 20,
            (value / this.scale) * 40,
            15
        );
        this.context.fillText(
            value.toString(),
            (value / this.scale) * 40 + 53,
            12 + index * 20,
            37
        );
        this.context.textAlign = 'right';
        let text = '';
        if (this.translatedTextArr && this.translatedTextArr.length > 0) {
            text = this.translatedTextArr[index];
        } else {
            text = this.metadata[index].text;
        }
        this.context.fillText(text, 47, 12 + index * 20, 47);
    }
    drawLine(x, y, X, Y) {
        this.context.beginPath();
        this.context.moveTo(x, y);
        this.context.lineTo(X, Y);
        if (this.isWhiteBackground) {
            this.context.strokeStyle = '#000';
        } else {
            this.context.strokeStyle = '#fff';
        }
        this.context.stroke();
        this.context.closePath();
    }
    getMax() {
        let count = 1;
        if (this.metadata && this.metadata.length > 0) {
            this.metadata.forEach(item => {
                if (item.value > count) {
                    count = item.value;
                }
            });
        }
        this.max = count;
        this.scale = Math.ceil(count / 40) * 10;
    }
}
