/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.
 */

@use 'sass:map';
@use '@angular/material' as mat;

@mixin generate-theme($material-theme, $supplemental-theme) {
    // Get the color config from the theme.
    $material-theme-color-config: mat.get-color-config($material-theme);
    $supplemental-theme-color-config: mat.get-color-config($supplemental-theme);

    // Get the palettes from the color-config.
    $material-theme-primary-palette: map.get($material-theme-color-config, 'primary');
    $material-theme-accent-palette: map.get($material-theme-color-config, 'accent');
    $material-theme-warn-palette: map.get($material-theme-color-config, 'warn');
    $supplemental-theme-surface-palette: map.get($supplemental-theme-color-config, 'primary');
    $supplemental-theme-success-palette: map.get($supplemental-theme-color-config, 'accent');
    $supplemental-theme-caution-palette: map.get($supplemental-theme-color-config, 'warn');

    // Get hues from palette
    $material-theme-primary-palette-darker: mat.get-color-from-palette($material-theme-primary-palette, darker);
    $material-theme-primary-palette-lighter: mat.get-color-from-palette($material-theme-primary-palette, lighter);
    $material-theme-primary-palette-default: mat.get-color-from-palette($material-theme-primary-palette, default);
    $material-theme-accent-palette-default: mat.get-color-from-palette($material-theme-accent-palette, default);

    // Canvas colors
    $supplemental-theme-surface-palette-default: mat.get-color-from-palette(
        $supplemental-theme-surface-palette,
        default
    );
    $supplemental-theme-surface-palette-lighter: mat.get-color-from-palette(
        $supplemental-theme-surface-palette,
        lighter
    );
    $supplemental-theme-surface-palette-darker: mat.get-color-from-palette($supplemental-theme-surface-palette, darker);
    $supplemental-theme-success-palette-lighter: mat.get-color-from-palette(
        $supplemental-theme-success-palette,
        lighter
    );
    $supplemental-theme-success-palette-50: mat.get-color-from-palette($supplemental-theme-success-palette, 50);
    $supplemental-theme-success-palette-900: mat.get-color-from-palette($supplemental-theme-success-palette, 900);
    $material-theme-warn-palette-darker: mat.get-color-from-palette($material-theme-warn-palette, darker);
    $supplemental-theme-caution-palette-darker: mat.get-color-from-palette($supplemental-theme-caution-palette, darker);

    // Shadows should always be darker. We explicitly set this so the SVG shadows are correct in both modes.
    $is-dark: map-get($supplemental-theme-color-config, is-dark);
    $drop-shadow-color: black;
    $connection-drop-shadow-color: if($is-dark, black, white);

    $supplemental-theme-surface-palette-darker-contrast: mat.get-color-from-palette(
        $supplemental-theme-surface-palette,
        darker-contrast
    );
    $supplemental-theme-surface-palette-lighter-contrast: mat.get-color-from-palette(
        $supplemental-theme-surface-palette,
        lighter-contrast
    );
    $surface-contrast: if(
        $is-dark,
        $supplemental-theme-surface-palette-darker-contrast,
        $supplemental-theme-surface-palette-lighter-contrast
    );
    $alternate-surface: if(
        $is-dark,
        rgba($supplemental-theme-surface-palette-darker-contrast, 0.28),
        rgba($supplemental-theme-surface-palette-lighter-contrast, 0.2)
    );

    .canvas-background {
        background-color: if(
            $is-dark,
            $supplemental-theme-surface-palette-darker,
            $supplemental-theme-surface-palette-lighter
        );
        background-image: linear-gradient(
                to right,
                if($is-dark, $supplemental-theme-success-palette-900, $supplemental-theme-success-palette-50) 1px,
                transparent 1px
            ),
            linear-gradient(
                to bottom,
                if($is-dark, $supplemental-theme-success-palette-900, $supplemental-theme-success-palette-50) 1px,
                transparent 1px
            );
    }

    /* svg styles */

    svg.canvas-svg {
        /*
          All components
      */

        g.component {
            font-family: mat.get-theme-typography($material-theme, body-1, font-family);
        }

        .transparent {
            fill: transparent;
        }

        g.component rect.body {
            fill: if($is-dark, $supplemental-theme-surface-palette-darker, $supplemental-theme-surface-palette-lighter);
        }

        rect.banner {
            fill: rgba(
                if($is-dark, $supplemental-theme-surface-palette-lighter, $supplemental-theme-surface-palette-darker),
                0.08
            );
        }

        rect.odd {
            fill: rgba(
                if($is-dark, $supplemental-theme-surface-palette-lighter, $supplemental-theme-surface-palette-darker),
                0.025
            );
        }

        rect.even {
            fill: if($is-dark, $supplemental-theme-surface-palette-darker, $supplemental-theme-surface-palette-lighter);
        }

        rect.row-border {
            fill: $alternate-surface;
        }

        g.component rect.body.unauthorized {
            fill: if($is-dark, $supplemental-theme-surface-palette-darker, $supplemental-theme-surface-palette-lighter);
        }

        g.component rect.border,
        g.connections rect.border {
            stroke: $alternate-surface;
            stroke-width: if(
                $is-dark,
                2,
                1
            ); // Dark mode gets a wider stroke to provide contrast between the canvas and components
        }

        g.component rect.border.unauthorized {
            stroke: $material-theme-warn-palette-darker !important;
        }

        g.component rect.border.ghost {
            stroke: $supplemental-theme-surface-palette-default !important;
        }

        g.component rect.processor-icon-container.unauthorized {
            fill: if($is-dark, $supplemental-theme-surface-palette-darker, $supplemental-theme-surface-palette-lighter);
        }

        g.component.selected rect.border {
            stroke: $material-theme-primary-palette-default !important;
        }

        text.stats-label {
            @extend .surface-contrast;
            font-family: mat.get-theme-typography($material-theme, body-1, font-family);
        }

        text.stats-value {
            fill: $material-theme-accent-palette-default;
        }

        text.stats-info {
            fill: $material-theme-primary-palette-default;
        }

        text.bulletin-icon {
            fill: if(
                $is-dark,
                $supplemental-theme-surface-palette-lighter-contrast,
                $supplemental-theme-surface-palette-darker-contrast
            );
        }

        rect.bulletin-background {
            fill: $material-theme-warn-palette-darker;
        }

        text.active-thread-count {
            fill: $material-theme-accent-palette-default;
        }

        text.component-comments {
            fill: $material-theme-primary-palette-default;
            stroke: $alternate-surface;
        }

        /*
          Selection
      */

        g.component.connectable-destination rect.border {
            stroke: #00ff00;
        }

        rect.component-selection,
        rect.drag-selection,
        rect.label-drag {
            stroke: if($is-dark, $material-theme-primary-palette-lighter, $material-theme-primary-palette-default);
            fill: transparent;
        }

        text.add-connect {
            fill: $material-theme-primary-palette-default;
        }

        /*
          Processor
      */
        #component-drop-shadow feFlood {
            flood-color: $drop-shadow-color;
        }

        rect.processor-read-write-stats {
            fill: if($is-dark, $supplemental-theme-surface-palette-darker, $supplemental-theme-surface-palette-lighter);
        }

        rect.processor-stats-border {
            fill: $alternate-surface;
        }

        text.processor-name {
            fill: if(
                $is-dark,
                $supplemental-theme-surface-palette-darker-contrast,
                $supplemental-theme-surface-palette-lighter-contrast
            );
        }

        text.processor-type {
            fill: $material-theme-primary-palette-default;
        }

        circle.is-primary-background {
            stroke: if(
                $is-dark,
                $supplemental-theme-surface-palette-lighter,
                $supplemental-theme-surface-palette-darker
            );
            fill: if($is-dark, $supplemental-theme-surface-palette-darker, $supplemental-theme-surface-palette-lighter);
        }

        text.is-primary {
            fill: if($is-dark, $supplemental-theme-surface-palette-lighter, $supplemental-theme-surface-palette-darker);
        }

        text.processor-bundle {
            fill: $supplemental-theme-surface-palette-default;
        }

        rect.processor-icon-container {
            fill: if($is-dark, $supplemental-theme-surface-palette-darker, $supplemental-theme-surface-palette-lighter);
        }

        circle.restricted-background {
            fill: if($is-dark, $supplemental-theme-surface-palette-darker, $supplemental-theme-surface-palette-lighter);
        }

        text.restricted {
            fill: $material-theme-warn-palette-darker;
        }

        /*
          Connection
      */
        #connection-full-drop-shadow feFlood {
            flood-color: $material-theme-warn-palette-darker;
        }

        g.connection {
            font-family: mat.get-theme-typography($material-theme, body-1, font-family);
        }

        g.connection rect.body {
            fill: if($is-dark, $supplemental-theme-surface-palette-darker, $supplemental-theme-surface-palette-lighter);
        }

        g.connection rect.body.unauthorized {
            fill: if($is-dark, $supplemental-theme-surface-palette-darker, $supplemental-theme-surface-palette-lighter);
        }

        g.connection rect.border.unauthorized {
            stroke: $material-theme-warn-palette-darker;
        }

        g.connection rect.border.full {
            stroke: $material-theme-accent-palette-default;
        }

        g.connection.selected rect.border {
            stroke: $supplemental-theme-caution-palette-darker;
        }

        path.connector {
            stroke: #ff0000;
        }

        path.connector.connectable {
            stroke: #00ff00;
        }

        g.connection path.connection-path {
            fill: none;
            stroke: $surface-contrast;
            filter: drop-shadow(
                0 3px 6px
                    if(
                        $is-dark,
                        $supplemental-theme-surface-palette-darker,
                        $supplemental-theme-surface-palette-lighter
                    )
            );
        }

        g.connection path.connection-path.full {
            stroke: $material-theme-warn-palette-darker;
        }

        g.connection path.connection-path.unauthorized {
            stroke: $material-theme-warn-palette-darker;
        }

        g.connection rect.backpressure-tick {
            fill: transparent;
        }

        g.connection rect.backpressure-tick.data-size-prediction.prediction-down,
        g.connection rect.backpressure-tick.object-prediction.prediction-down {
            fill: if($is-dark, $supplemental-theme-surface-palette-darker, $supplemental-theme-surface-palette-lighter);
        }

        g.connection rect.backpressure-tick.data-size-prediction,
        g.connection rect.backpressure-tick.object-prediction {
            fill: $alternate-surface;
        }

        g.connection rect.backpressure-tick.data-size-prediction.not-configured,
        g.connection rect.backpressure-tick.object-prediction.not-configured,
        g.connection rect.backpressure-tick.data-size-prediction.prediction-down.not-configured,
        g.connection rect.backpressure-tick.object-prediction.prediction-down.not-configured {
            fill: transparent;
        }

        g.connection rect.backpressure-tick.not-configured {
            fill: $supplemental-theme-surface-palette-default;
        }

        g.connection rect.backpressure-object,
        g.connection rect.backpressure-data-size {
            fill: $alternate-surface;
        }

        g.connection rect.backpressure-object.not-configured,
        g.connection rect.backpressure-data-size.not-configured {
            fill: transparent;
        }

        g.connection rect.backpressure-percent {
            fill: $supplemental-theme-success-palette-lighter;
        }

        g.connection rect.backpressure-percent.warning {
            fill: $supplemental-theme-caution-palette-darker;
        }

        g.connection rect.backpressure-percent.error {
            fill: $material-theme-warn-palette-darker;
        }

        /* ghost connection */

        g.connection.ghost path.connection-path,
        g.connection.ghost rect.connection-label {
            stroke: $supplemental-theme-surface-palette-default;
        }

        g.connection path.connection-selection-path {
            stroke: $supplemental-theme-caution-palette-darker;
            fill: none;
        }

        g.connection path.connection-path-selectable {
            fill: none;
        }

        g.connection rect.startpoint {
            stroke: #ff0000;
            fill: #ff0000;
        }

        g.connection rect.midpoint {
            stroke: $supplemental-theme-caution-palette-darker;
            fill: $supplemental-theme-caution-palette-darker;
        }

        g.connection rect.endpoint {
            stroke: #0000ff;
            fill: #0000ff;
        }

        /* labels */

        g.label path.resizable-triangle {
            fill: rgba($supplemental-theme-surface-palette-lighter-contrast, 0.2);
            stroke: rgba($supplemental-theme-surface-palette-lighter-contrast, 0.2);
        }

        /* funnels */

        text.funnel-icon {
            fill: $material-theme-accent-palette-default;
        }

        /* ports */

        text.port-name {
            @extend .surface-contrast;
        }

        text.port-icon {
            fill: $material-theme-accent-palette-default;
        }

        /* process groups */

        rect.process-group-stats-in-out {
            fill: if($is-dark, $supplemental-theme-surface-palette-darker, $supplemental-theme-surface-palette-lighter);
        }

        rect.process-group-stats-border {
            fill: if($is-dark, $material-theme-primary-palette-default, $material-theme-primary-palette-darker);
        }

        rect.process-group-banner,
        rect.remote-process-group-banner {
            fill: if($is-dark, $material-theme-primary-palette-default, $material-theme-primary-palette-darker);
        }

        text.version-control,
        text.not-transmitting,
        text.transmitting,
        text.process-group-transmitting,
        text.invalid,
        text.running,
        text.stopped,
        text.process-group-running,
        text.process-group-stopped {
            text-shadow: if($is-dark, 0 0 4px rgba(0, 0, 0, 1), 0 0 4px rgba(255, 255, 255, 1));
        }

        text.process-group-contents-count {
            fill: $material-theme-accent-palette-default;
            font-family: mat.get-theme-typography($material-theme, body-1, font-family);
        }

        g.process-group.drop rect.border {
            stroke: #0000ff;
        }

        /* remote process group */

        rect.remote-process-group-stats-border {
            fill: $alternate-surface;
        }

        rect.remote-process-group-received-stats {
            fill: if($is-dark, $supplemental-theme-surface-palette-darker, $supplemental-theme-surface-palette-lighter);
        }

        text.remote-process-group-uri {
            fill: if($is-dark, $material-theme-primary-palette-lighter, $material-theme-primary-palette-default);
        }

        text.remote-process-group-transmission-secure {
            fill: if($is-dark, $material-theme-primary-palette-lighter, $material-theme-primary-palette-default);
        }

        text.remote-process-group-last-refresh {
            fill: if($is-dark, $material-theme-primary-palette-lighter, $material-theme-primary-palette-default);
        }
    }
}
