/*
 * Copyright 2021 Google LLC
 *
 * 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.
 *
 * ---------------------------------------------------------------------
 *
 * Portions of this file were modified and ported to Vala by Victor Vintorez in 2026.
 * These modifications are licensed under the European Union Public License (EUPL),
 * Version 1.2 or later. You may obtain a copy of the License at:
 * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
 */

using GLib;

namespace MaterialColorUtilities {
	/** Named colors, otherwise known as tokens, or roles, in the Material Design system. */
	public sealed class MaterialDynamicColors : Object {
		private MaterialDynamicColors() {}

		private static ColorSpec? _color_spec;
		private static ColorSpec color_spec {
			get {
				if (_color_spec == null) _color_spec = new ColorSpec2026();
				return (!) _color_spec;
			}
		}

		public static DynamicColor highest_surface(DynamicScheme s) {
			return color_spec.highest_surface(s);
		}

		////////////////////////////////////////////////////////////////
		// Main Palettes                                              //
		////////////////////////////////////////////////////////////////

		public static DynamicColor primary_palette_key_color() {
			return color_spec.primary_palette_key_color;
		}

		public static DynamicColor secondary_palette_key_color() {
			return color_spec.secondary_palette_key_color;
		}

		public static DynamicColor tertiary_palette_key_color() {
			return color_spec.tertiary_palette_key_color;
		}

		public static DynamicColor neutral_palette_key_color() {
			return color_spec.neutral_palette_key_color;
		}

		public static DynamicColor neutral_variant_palette_key_color() {
			return color_spec.neutral_variant_palette_key_color;
		}

		public static DynamicColor error_palette_key_color() {
			return color_spec.error_palette_key_color;
		}

		////////////////////////////////////////////////////////////////
		// Surfaces [S]                                               //
		////////////////////////////////////////////////////////////////

		public static DynamicColor background() {
			return color_spec.background;
		}

		public static DynamicColor on_background() {
			return color_spec.on_background;
		}

		public static DynamicColor surface() {
			return color_spec.surface;
		}

		public static DynamicColor surface_dim() {
			return color_spec.surface_dim;
		}

		public static DynamicColor surface_bright() {
			return color_spec.surface_bright;
		}

		public static DynamicColor surface_container_lowest() {
			return color_spec.surface_container_lowest;
		}

		public static DynamicColor surface_container_low() {
			return color_spec.surface_container_low;
		}

		public static DynamicColor surface_container() {
			return color_spec.surface_container;
		}

		public static DynamicColor surface_container_high() {
			return color_spec.surface_container_high;
		}

		public static DynamicColor surface_container_highest() {
			return color_spec.surface_container_highest;
		}

		public static DynamicColor on_surface() {
			return color_spec.on_surface;
		}

		public static DynamicColor surface_variant() {
			return color_spec.surface_variant;
		}

		public static DynamicColor on_surface_variant() {
			return color_spec.on_surface_variant;
		}

		public static DynamicColor inverse_surface() {
			return color_spec.inverse_surface;
		}

		public static DynamicColor inverse_on_surface() {
			return color_spec.inverse_on_surface;
		}

		public static DynamicColor outline() {
			return color_spec.outline;
		}

		public static DynamicColor outline_variant() {
			return color_spec.outline_variant;
		}

		public static DynamicColor shadow() {
			return color_spec.shadow;
		}

		public static DynamicColor scrim() {
			return color_spec.scrim;
		}

		public static DynamicColor surface_tint() {
			return color_spec.surface_tint;
		}

		////////////////////////////////////////////////////////////////
		// Primaries [P]                                              //
		////////////////////////////////////////////////////////////////

		public static DynamicColor primary() {
			return color_spec.primary;
		}

		public static DynamicColor primary_dim() {
			return color_spec.primary_dim;
		}

		public static DynamicColor on_primary() {
			return color_spec.on_primary;
		}

		public static DynamicColor primary_container() {
			return color_spec.primary_container;
		}

		public static DynamicColor on_primary_container() {
			return color_spec.on_primary_container;
		}

		public static DynamicColor inverse_primary() {
			return color_spec.inverse_primary;
		}

		/////////////////////////////////////////////////////////////////
		// Primary Fixed Colors [PF]                                   //
		/////////////////////////////////////////////////////////////////

		public static DynamicColor primary_fixed() {
			return color_spec.primary_fixed;
		}

		public static DynamicColor primary_fixed_dim() {
			return color_spec.primary_fixed_dim;
		}

		public static DynamicColor on_primary_fixed() {
			return color_spec.on_primary_fixed;
		}

		public static DynamicColor on_primary_fixed_variant() {
			return color_spec.on_primary_fixed_variant;
		}

		////////////////////////////////////////////////////////////////
		// Secondaries [Q]                                            //
		////////////////////////////////////////////////////////////////

		public static DynamicColor secondary() {
			return color_spec.secondary;
		}

		public static DynamicColor secondary_dim() {
			return color_spec.secondary_dim;
		}

		public static DynamicColor on_secondary() {
			return color_spec.on_secondary;
		}

		public static DynamicColor secondary_container() {
			return color_spec.secondary_container;
		}

		public static DynamicColor on_secondary_container() {
			return color_spec.on_secondary_container;
		}

		/////////////////////////////////////////////////////////////////
		// Secondary Fixed Colors [QF]                                 //
		/////////////////////////////////////////////////////////////////

		public static DynamicColor secondary_fixed() {
			return color_spec.secondary_fixed;
		}

		public static DynamicColor secondary_fixed_dim() {
			return color_spec.secondary_fixed_dim;
		}

		public static DynamicColor on_secondary_fixed() {
			return color_spec.on_secondary_fixed;
		}

		public static DynamicColor on_secondary_fixed_variant() {
			return color_spec.on_secondary_fixed_variant;
		}

		////////////////////////////////////////////////////////////////
		// Tertiaries [T]                                             //
		////////////////////////////////////////////////////////////////

		public static DynamicColor tertiary() {
			return color_spec.tertiary;
		}

		public static DynamicColor tertiary_dim() {
			return color_spec.tertiary_dim;
		}

		public static DynamicColor on_tertiary() {
			return color_spec.on_tertiary;
		}

		public static DynamicColor tertiary_container() {
			return color_spec.tertiary_container;
		}

		public static DynamicColor on_tertiary_container() {
			return color_spec.on_tertiary_container;
		}

		/////////////////////////////////////////////////////////////////
		// Tertiary Fixed Colors [TF]                                  //
		/////////////////////////////////////////////////////////////////

		public static DynamicColor tertiary_fixed() {
			return color_spec.tertiary_fixed;
		}

		public static DynamicColor tertiary_fixed_dim() {
			return color_spec.tertiary_fixed_dim;
		}

		public static DynamicColor on_tertiary_fixed() {
			return color_spec.on_tertiary_fixed;
		}

		public static DynamicColor on_tertiary_fixed_variant() {
			return color_spec.on_tertiary_fixed_variant;
		}

		////////////////////////////////////////////////////////////////
		// Errors [E]                                                 //
		////////////////////////////////////////////////////////////////

		public static DynamicColor error() {
			return color_spec.error;
		}

		public static DynamicColor error_dim() {
			return color_spec.error_dim;
		}

		public static DynamicColor on_error() {
			return color_spec.on_error;
		}

		public static DynamicColor error_container() {
			return color_spec.error_container;
		}

		public static DynamicColor on_error_container() {
			return color_spec.on_error_container;
		}

		////////////////////////////////////////////////////////////////
		// Android-only colors                                        //
		////////////////////////////////////////////////////////////////

		/**
		 * These colors were present in Android framework before Android U, and used by MDC controls. They
		 * should be avoided, if possible. It's unclear if they're used on multiple backgrounds, and if
		 * they are, they can't be adjusted for contrast.* For now, they will be set with no background,
		 * and those won't adjust for contrast, avoiding issues.
		 *
		 * <p>* For example, if the same color is on a white background _and_ black background, there's no
		 * way to increase contrast with either without losing contrast with the other.
		 */

		// colorControlActivated documented as colorAccent in M3 & GM3.
		// colorAccent documented as colorSecondary in M3 and colorPrimary in GM3.
		// Android used Material's Container as Primary/Secondary/Tertiary at launch.
		// Therefore, this is a duplicated version of Primary Container.
		public static DynamicColor control_activated() {
			return color_spec.control_activated;
		}

		// colorControlNormal documented as textColorSecondary in M3 & GM3.
		// In Material, textColorSecondary points to onSurfaceVariant in the non-disabled state,
		// which is Neutral Variant T30/80 in light/dark.
		public static DynamicColor control_normal() {
			return color_spec.control_normal;
		}

		// colorControlHighlight documented, in both M3 & GM3:
		// Light mode: #1f000000 dark mode: #33ffffff.
		// These are black and white with some alpha.
		// 1F hex = 31 decimal; 31 / 255 = 12% alpha.
		// 33 hex = 51 decimal; 51 / 255 = 20% alpha.
		// DynamicColors do not support alpha currently, and _may_ not need it for this use case,
		// depending on how MDC resolved alpha for the other cases.
		// Returning black in dark mode, white in light mode.
		public static DynamicColor control_highlight() {
			return color_spec.control_highlight;
		}

		// textColorPrimaryInverse documented, in both M3 & GM3, documented as N10/N90.
		public static DynamicColor text_primary_inverse() {
			return color_spec.text_primary_inverse;
		}

		// textColorSecondaryInverse and textColorTertiaryInverse both documented, in both M3 & GM3, as
		// NV30/NV80
		public static DynamicColor text_secondary_and_tertiary_inverse() {
			return color_spec.text_secondary_and_tertiary_inverse;
		}

		// textColorPrimaryInverseDisableOnly documented, in both M3 & GM3, as N10/N90
		public static DynamicColor text_primary_inverse_disable_only() {
			return color_spec.text_primary_inverse_disable_only;
		}

		// textColorSecondaryInverse and textColorTertiaryInverse in disabled state both documented,
		// in both M3 & GM3, as N10/N90
		public static DynamicColor text_secondary_and_tertiary_inverse_disabled() {
			return color_spec.text_secondary_and_tertiary_inverse_disabled;
		}

		// textColorHintInverse documented, in both M3 & GM3, as N10/N90
		public static DynamicColor text_hint_inverse() {
			return color_spec.text_hint_inverse;
		}

		////////////////////////////////////////////////////////////////
		// All Colors                                                 //
		////////////////////////////////////////////////////////////////

		/** All dynamic colors in Material Design system. */
		public static DynamicColor[] all_dynamic_colors() {
			return new DynamicColor[] {
					   MaterialDynamicColors.primary_palette_key_color(),
					       MaterialDynamicColors.secondary_palette_key_color(),
					       MaterialDynamicColors.tertiary_palette_key_color(),
					       MaterialDynamicColors.neutral_palette_key_color(),
					       MaterialDynamicColors.neutral_variant_palette_key_color(),
					       MaterialDynamicColors.error_palette_key_color(),
					       MaterialDynamicColors.background(),
					       MaterialDynamicColors.on_background(),
					       MaterialDynamicColors.surface(),
					       MaterialDynamicColors.surface_dim(),
					       MaterialDynamicColors.surface_bright(),
					       MaterialDynamicColors.surface_container_lowest(),
					       MaterialDynamicColors.surface_container_low(),
					       MaterialDynamicColors.surface_container(),
					       MaterialDynamicColors.surface_container_high(),
					       MaterialDynamicColors.surface_container_highest(),
					       MaterialDynamicColors.on_surface(),
					       MaterialDynamicColors.surface_variant(),
					       MaterialDynamicColors.on_surface_variant(),
					       MaterialDynamicColors.inverse_surface(),
					       MaterialDynamicColors.inverse_on_surface(),
					       MaterialDynamicColors.outline(),
					       MaterialDynamicColors.outline_variant(),
					       MaterialDynamicColors.shadow(),
					       MaterialDynamicColors.scrim(),
					       MaterialDynamicColors.surface_tint(),
					       MaterialDynamicColors.primary(),
					       MaterialDynamicColors.primary_dim(),
					       MaterialDynamicColors.on_primary(),
					       MaterialDynamicColors.primary_container(),
					       MaterialDynamicColors.on_primary_container(),
					       MaterialDynamicColors.inverse_primary(),
					       MaterialDynamicColors.primary_fixed(),
					       MaterialDynamicColors.primary_fixed_dim(),
					       MaterialDynamicColors.on_primary_fixed(),
					       MaterialDynamicColors.on_primary_fixed_variant(),
					       MaterialDynamicColors.secondary(),
					       MaterialDynamicColors.secondary_dim(),
					       MaterialDynamicColors.on_secondary(),
					       MaterialDynamicColors.secondary_container(),
					       MaterialDynamicColors.on_secondary_container(),
					       MaterialDynamicColors.secondary_fixed(),
					       MaterialDynamicColors.secondary_fixed_dim(),
					       MaterialDynamicColors.on_secondary_fixed(),
					       MaterialDynamicColors.on_secondary_fixed_variant(),
					       MaterialDynamicColors.tertiary(),
					       MaterialDynamicColors.tertiary_dim(),
					       MaterialDynamicColors.on_tertiary(),
					       MaterialDynamicColors.tertiary_container(),
					       MaterialDynamicColors.on_tertiary_container(),
					       MaterialDynamicColors.tertiary_fixed(),
					       MaterialDynamicColors.tertiary_fixed_dim(),
					       MaterialDynamicColors.on_tertiary_fixed(),
					       MaterialDynamicColors.on_tertiary_fixed_variant(),
					       MaterialDynamicColors.error(),
					       MaterialDynamicColors.error_dim(),
					       MaterialDynamicColors.on_error(),
					       MaterialDynamicColors.error_container(),
					       MaterialDynamicColors.on_error_container(),
					       MaterialDynamicColors.control_activated(),
					       MaterialDynamicColors.control_normal(),
					       MaterialDynamicColors.control_highlight(),
					       MaterialDynamicColors.text_primary_inverse(),
					       MaterialDynamicColors.text_secondary_and_tertiary_inverse(),
					       MaterialDynamicColors.text_primary_inverse_disable_only(),
					       MaterialDynamicColors.text_secondary_and_tertiary_inverse_disabled(),
					       MaterialDynamicColors.text_hint_inverse(),
			};
		}
	}
}
