@use 'sass:color';
@use "sass:map";
//
// Mixins
// --------------------------------------------------

@mixin compact {
	$selector: &;
	@at-root [zoteroUIDensity="compact"] {
		@if $selector {
			#{$selector} {
				@content;
			}
		}
		
		@else {
			@content;
		}
	}
}

@mixin comfortable {
	$selector: &;
	@at-root [zoteroUIDensity="comfortable"] {
		@if $selector {
			#{$selector} {
				@content;
			}
		}

		@else {
			@content;
		}
	}
}

// State mixin
@mixin state($states...) {

	@each $state in $states {
		$string: $state;

		@each $token in ">", "+", "~" {
			$string: str-replace($string, $token, " ");
		}

		$string: str-replace($string, "  ", " ");

		$selectors: str-parse($string, " ");

		@each $sel in $selectors {
			@if str-index("#{&}", $sel) !=null {
				@at-root #{selector-replace(&, $sel, $state)} {
					@content;
				}
			}
		}
	}
}

// Variant mixin (alias)
@mixin variant($args...) {
	@include state($args...) {
		@content;
	}
}

// @NOTE: this mixin uses `state` mixin, therefore must be used in a selector nested
//        underneath selectors listed in arguments, e.g., .virtualized-table .row 
//        by default. See `state` mixin for more details.
@mixin focus-states(
	$selectedState: '.row.selected',
	$focused: '.focus-states-target:focus-within'
	) {
	@media (prefers-color-scheme: light) {
		@content("light");
		
		@include state($selectedState) {
			@include state($focused) {
				@content("white");
			}
		}
	}

	@media (prefers-color-scheme: dark) {
		@content("dark");
		
		@include state($selectedState) {
			@include state($focused) {
				@content("white");
			}
		}
	}
}

// An implementation of Firefox light-dark() CSS mixin, which is not supported in 102
@mixin light-dark($prop, $light-color, $dark-color) {
	@media (prefers-color-scheme: light) {
		#{$prop}: $light-color;
	}
	@media (prefers-color-scheme: dark) {
		#{$prop}: $dark-color;
	}
}

@mixin color-scheme {
	@media (prefers-color-scheme: light) {
		@content("light");
	}
	
	@media (prefers-color-scheme: dark) {
		@content("dark");
	}
}

@mixin clicky-item {
	display: flex;
	align-items: flex-start;
	gap: 4px;
	padding-inline-start: 4px;
	overflow: hidden;
	border-radius: 5px;

	&:not([disabled]):hover {
		background-color: var(--fill-quinary);
	}
	
	&:not([disabled]):active {
		background-color: var(--fill-quarternary);
	}

	.icon {
		height: calc(1.3333333333*var(--zotero-font-size));
		padding-top: 0.25em; 
	}

	.annotation-icon {
		-moz-context-properties: fill;
		padding-block: 2px;
	}

	.label {
		display: -webkit-box;
		-webkit-box-orient: vertical;
		-webkit-line-clamp: 10;
		width: 0; // Needed to allow the label to shrink for some reason
		flex: 1;
		overflow: hidden;
		padding-block: 2px;
	}
}

@mixin meta-table {
	display: grid;
	grid-template-columns: max-content 1fr;
	column-gap: 8px;
	row-gap: 2px;
	width: inherit;

	.meta-row {
		display: grid;
		grid-template-columns: subgrid;
		grid-column: span 2;

		&[hidden] {
			display: none;
		}	

		&:not(:hover):not(:focus-within) .show-on-hover,
		&.noHover .show-on-hover {
			clip-path: inset(50%);
			&.no-display {
				width: 0;
				height: 0;
				padding: 0;
				position: absolute;
			}
		}
		.meta-data {
			width: 0;
			min-width: 100%;
			display: flex;

			toolbarbutton {
				margin-inline-start: 4px;
			}
	
		}
		editable-text {
			flex: 1; // stretch value field as much as possible
			max-width: 100%; // stay within .meta-data when the itemBox is narrow
			.input {
				// allow input to be shrunk by other elements when the itemBox is narrow
				min-width: 0;
			}
		}
	
		.meta-label {
			display: flex;
			font-weight: normal;
			text-align: end;
			color: var(--fill-secondary);

			&[fieldname^="creator"] {
				justify-content: space-between;
				align-items: center;
			}
			> label {
				margin-top: 2px;
				@include comfortable {
					margin-top: 3px;
				}
			}
		}
		
		.key {
			width: 100%;
		}
		
		@include contains-toolbarbutton-aligned-to-row;
	}
}

/* Hide icons on macOS. We use :is() to work around weird behavior in Fx101 where a regular child
   selector doesn't match the first time the menu is opened. */
@mixin macOS-hide-menu-icons {
	$selector: &;
	@at-root {
		@media (-moz-platform: macos) {
			// Yes, every single one of these :is-es is necessary!
			:is(:is(#{$selector}) .menuitem-iconic, :is(#{$selector}) .menu-iconic) {
				list-style-image: none !important;

				.menu-icon {
					display: none !important;
				}
			}
		}
	}
}

@mixin inactive-opacity {
	$selector: &;
	@at-root {
		@media (-moz-platform: macos) or (-moz-platform: linux) {
			#{$selector} {
				&:-moz-window-inactive {
					opacity: 0.6;
				}
			}
		}
	}
}

// Normalize margins/paddings for form controls on macOS
@mixin macOS-normalize-controls {
	@media (-moz-platform: macos) {
		:is(button, toolbarbutton) .button-text {
			margin-block: 1px 0;
			margin-inline: 3px;
		}

		radiogroup {
			margin: 0;
			column-gap: 8px;
		}

		radio, checkbox {
			margin: 0;
			gap: 6px;
		}

		radio :is(.radio-check, .radio-check[checked], .radio-icon, .radio-label),
		checkbox :is(.checkbox-check, .checkbox-check[checked], .checkbox-icon, .checkbox-label) {
			margin: 0;

			// Can't break these out into separate rules because of specificity:

			&:is(.radio-check, .checkbox-check) {
				margin-inline-start: -2px;
			}

			&:is(.checkbox-label) {
				margin-top: -1px;
			}
		}
	}
}

/*
	This mixin replaces the default focus-rings - those are platform-specific, do not show up on some
	components (e.g. toolbarbutton) and sometimes are too wide (e.g. around textfield on macOS).
	Box-shadow is used to be able to set the radius.
*/
@mixin focus-ring($thin: false, $selector: ":focus-visible") {
	@media (-moz-platform: windows) {
		@include windows-focus-ring($selector);
	}
	@media not (-moz-platform: windows) {
		@include non-windows-focus-ring($thin, $selector);
	}
}

@mixin windows-focus-ring($selector: ":focus-visible") {
	&#{$selector} {
		outline: var(--color-focus-outer-border) solid var(--width-focus-outer-border);
		outline-offset: var(--width-focus-border);
		box-shadow: 0 0 0 var(--width-focus-border) var(--color-focus-border);
	}
}

@mixin non-windows-focus-ring($thin: false, $selector: ":focus-visible") {
	&#{$selector} {
		// fx115: Necessary to hide default focus ring
		outline: none;
		box-shadow: 0 0 0 var(--width-focus-border) var(--color-focus-border);

		@if $thin {
			--width-focus-border: 1px;
			--color-focus-border: var(--color-accent);
		}
	}
}

@mixin derive-colors($colors) {
	@each $name, $color in $colors {
		--#{$name}: #{$color};
	}

	// composite (opaque) colors
	--color-quinary-on-background: #{color.mix(
		map.get($colors, "color-background"), color.change(map.get($colors, "fill-quinary"), $alpha: 1), 100% * (1 - color.alpha(map.get($colors, "fill-quinary")))
	)};
	--color-quarternary-on-background: #{color.mix(
		map.get($colors, "color-background"), color.change(map.get($colors, "fill-quarternary"), $alpha: 1), 100% * (1 - color.alpha(map.get($colors, "fill-quarternary")))
	)};
	--color-quinary-on-sidepane: #{color.mix(
		map.get($colors, "color-sidepane"), color.change(map.get($colors, "fill-quinary"), $alpha: 1), 100% * (1 - color.alpha(map.get($colors, "fill-quinary")))
	)};
	--color-quarternary-on-sidepane: #{color.mix(
		map.get($colors, "color-sidepane"), color.change(map.get($colors, "fill-quarternary"), $alpha: 1), 100% * (1 - color.alpha(map.get($colors, "fill-quarternary")))
	)};
	--color-stripe-on-background: #{color.mix(
		map.get($colors, "color-background"), color.change(map.get($colors, "color-stripe"), $alpha: 1), 100% * (1 - color.alpha(map.get($colors, "color-stripe")))
	)};
	--color-menu-opaque: rgb(
		#{color.alpha(map.get($colors, "color-menu")) * color.red(map.get($colors, "color-menu"))},
		#{color.alpha(map.get($colors, "color-menu")) * color.green(map.get($colors, "color-menu"))},
		#{color.alpha(map.get($colors, "color-menu")) * color.blue(map.get($colors, "color-menu"))}
	);

	// opaque tag colors for tag swatches
	@each $tag in "blue", "gray", "green", "indigo", "magenta", "orange", "plum", "purple", "red", "teal", "yellow", {
		--tag-#{$tag}-opaque: #{color.change(map.get($colors, "tag-#{$tag}"), $alpha: 1)};
	}

	// background materials
	--material-background: var(--color-background);
	--material-background50: var(--color-background50);
	--material-background70: var(--color-background70);
	--material-button: var(--color-button);
	--material-control: var(--color-control);
	--material-menu: var(--color-menu);
	--material-sidepane: var(--color-sidepane);
	--material-tabbar: var(--color-tabbar);
	--material-toolbar: var(--color-toolbar);
	--material-mix-quinary: var(--color-quinary-on-background);
	--material-mix-quarternary: var(--color-quarternary-on-background);
	--material-stripe: var(--color-stripe-on-background);

	// border materials
	--material-border-transparent: 1px solid transparent;
	--material-border: 1px solid var(--color-border);
	--material-border50: 1px solid var(--color-border50);
	--material-panedivider: 1px solid var(--color-panedivider);
	--material-border-quinary: 1px solid var(--fill-quinary);
	--material-border-quarternary: 1px solid var(--fill-quarternary);
}

@mixin contain-richlistbox {
	// richlistbox elements are crazy and will expand beyond the window size
	// unless all/most elements in the hierarchy that contain that
	// richlistbox have a min-height: 0 set
	vbox, hbox, box, groupbox, dialog {
		min-height: 0;
	}
}

@mixin contains-toolbarbutton-aligned-to-row {
	toolbarbutton {
		@include focus-ring;

		// needed to have the outline appear on all platforms
		appearance: none;
		-moz-appearance: none;
		// Make all buttons tighter to not stretch the rows
		height: auto;
		width: auto;
		border-radius: 2px;
		// Prevent the button from vertically stretching on multi-line fields (e.g., title)
		align-self: baseline;
		// Align the button to the center of the first line of text
		padding: 0.25em 1px 1px;
	}
}

@mixin contains-toolbarbutton-show-on-hover {
	toolbarbutton {
		margin-inline-start: auto;
			& > image {
				visibility: hidden;
			}
		}

	&:is(:hover, :focus-within) toolbarbutton > image {
		visibility: visible;
	}
}

@mixin elements-custom-head {
	.custom-head {
		display: flex;
		flex-direction: row;
		align-self: stretch;
		gap: 8px;
		padding: 6px 8px;
		background: var(--material-sidepane);
		border-bottom: var(--material-panedivider);
		height: 28px;
		align-items: center;

		&:empty {
			display: none;
		}

		button {
			height: 26px;
			margin: 0;
			@media (-moz-platform: macos) {
				margin: 0px -2px;
			}
			flex-grow: 1;
		}
	}
}