import * as d3 from "d3";
import {brushX, event, ScaleLinear, ScaleTime} from "d3";
import {DataPoint, Margins, Size} from "../MySitePageTypes";
import React from "react";

export const transformXYvaluesToAreas = (x: (time: Date) => number, y: (value: number) => number, y0: number) => {
    return d3.area<DataPoint>()
        .x((d, _) => x(d.time))
        .y0(y0)
        .y1(d => y(d.value));
};

export const transformXYvaluesToLines = (x: (time: Date) => number, y: (value: number) => number) => {
    return d3.line<DataPoint>()
        .x((d, _) => x(d.time))
        .y(d => y(d.value));
};

export const appendY1AxisTicks = (graph: d3.Selection<SVGSVGElement, unknown, null, undefined>, y: ScaleLinear<number, number>, margins: Margins) => {
    graph
        .selectAll(".y1Ticks")
        .remove();

    graph
        .append("g")
        .attr("class", "y1Ticks")
        .attr("transform", `translate(${margins.left * 3},0)`)
        .call(d3.axisLeft(y))
        .call((g) => g.select("domain").remove())
        .call(g => g.select(".tick:last-of-type text").clone()
            .attr("x", 3)
            .attr("text-anchor", "start")
            .attr("font-weight", "bold"));
};

export const appendY2AxisTicks = (graph: d3.Selection<SVGSVGElement, unknown, null, undefined>, y: ScaleLinear<number, number>, xAxisPosition: number) => {
    graph
        .selectAll(".y2Ticks")
        .remove();

    graph
        .append("g")
        .attr("class", "y2Ticks")
        .attr("transform", `translate(${xAxisPosition},0)`)
        .call(d3.axisRight(y))
        .call((g) => g.select("domain").remove())
        .call(g => g.select(".tick:last-of-type text").clone()
            .attr("x", 3)
            .attr("text-anchor", "start")
            .attr("font-weight", "bold"));
};

export const appendXAxisTicks = (graph: d3.Selection<SVGSVGElement, unknown, null, undefined>, x: ScaleTime<number, number>, size: Size, margins: Margins) => {
    graph
        .selectAll(".xTicks")
        .remove();

    graph
        .append("g")
        .attr("class", "xTicks")
        .attr("transform", `translate(0,${size.height - margins.bottom})`)
        .call(d3.axisBottom(x).ticks(size.width / 80).tickSizeOuter(0));
};

export const appendBrushXAxisTicks = (brush: d3.Selection<SVGGElement, unknown, null, undefined>, x: ScaleTime<number, number>, size: Size, margins: Margins) => {
    brush
        .selectAll(".xTicks")
        .remove();


    brush
        .append("g")
        .attr("class", "xTicks")
        .attr("transform", `translate(0,${size.height - margins.bottom})`)
        .call(d3.axisBottom(x).ticks(size.width / 80).tickSizeOuter(0));
};


export const appendY1axisDescription = (axisText: string, x = 0, y = 0) => {
    return <text transform={"rotate(-90)"}
                 y={x}
                 x={-y}
                 textAnchor={"middle"}
                 dy={"1em"}
    >{axisText}
    </text>;
};

export const filterData = (dataToFilter: DataPoint[], from: Date, to: Date) => {
    return dataToFilter.filter((d: DataPoint) => d.time >= from && d.time <= to);
};


type GraphColors = {
    fill: string,
    stroke: string
}

export const graphColors: GraphColors[] = [
    {
        fill: "#81d4fa",
        stroke: "#4ba3c7"
    },
    {
        fill: "#ffc107",
        stroke: "#c79100"
    },
    {
        fill: "#ff5722",
        stroke: "#c41c00"
    },
    {
        fill: "#ce93d8",
        stroke: "#9c64a6"
    },
];

export const strokeWidth = 3;
export const legendRowHeight = 20;
export const legendSymbolSize = 10;

export const legendOffset = {
    textXOffset: 24,
    bottom: 0,
    top: 0,
    left: 0,
    right: 70
};

export class StaticLegend extends React.Component<{ index?: number, staticId: number, text: string, x: number, y: number, dashed?: boolean }> {
    render() {
        return <>
            <line x1={this.props.x}
                  y1={this.props.y + 10}
                  x2={this.props.x + legendSymbolSize}
                  y2={this.props.y + 10}
                  style={{
                      stroke: (this.props.index || this.props.index === 0) ? graphColors[this.props.index].stroke : "#000000",
                      strokeWidth: strokeWidth,
                      strokeDasharray: this.props.dashed ? "3 4 3" : ""
                  }}
            />
            <text y={this.props.y}
                  x={this.props.x + legendOffset.textXOffset}
                  textAnchor={"left"}
                  dy={"1em"}
            >{`${this.props.text} #${this.props.staticId}`}
            </text>
        </>;
    }
}

export class DynamicLegend extends React.Component<{ index: number, dynamicId: number, text: string, x: number, y: number }> {
    render() {
        return <>
            <rect
                x={this.props.x}
                y={this.props.y + strokeWidth + (this.props.index + 1) * legendRowHeight}
                width={legendSymbolSize}
                height={legendSymbolSize}
                style={{
                    fill: graphColors[this.props.index].fill,
                    stroke: graphColors[this.props.index].stroke,
                    strokeWidth: strokeWidth
                }}
            />
            <text y={this.props.y + (this.props.index + 1) * legendRowHeight}
                  x={this.props.x + legendOffset.textXOffset}
                  textAnchor={"left"}
                  dy={"1em"}
            >{`${this.props.text} #${this.props.dynamicId}`}
            </text>
        </>
    }
}