import type { PropertyValueMap } from 'lit';
import { css, html, LitElement } from 'lit';
import { customElement, property, state } from 'lit/decorators.js';
import type { GitFileStatus } from '@gitlens/git/models/fileStatus.js';
import { getGitFileStatusText } from '@gitlens/git/utils/fileStatus.utils.js';

@customElement('gl-git-status')
export class GlGitStatus extends LitElement {
	static override styles = [
		css`
			:host-context(.vscode-high-contrast:not(.vscode-high-contrast-light)),
			:host-context(.vscode-dark) {
				--gl-git-status-ignored: #969696;
				--gl-git-status-untracked: #6c6c6c;
				--gl-git-status-added: #388a34;
				--gl-git-status-deleted: #9e121d;
				--gl-git-status-modified: #1b80b2;
				--gl-git-status-renamed: #c63;
				--gl-git-status-copied: #692c77;
				--gl-git-status-conflict: #7f4e7e;
				--gl-git-status-unknown: #6c6c6c;
			}

			:host-context(.vscode-high-contrast-light),
			:host-context(.vscode-light) {
				--gl-git-status-ignored: #969696;
				--gl-git-status-untracked: #6c6c6c;
				--gl-git-status-added: #388a34;
				--gl-git-status-deleted: #9e121d;
				--gl-git-status-modified: #1b80b2;
				--gl-git-status-renamed: #c63;
				--gl-git-status-copied: #692c77;
				--gl-git-status-conflict: #7f4e7e;
				--gl-git-status-unknown: #6c6c6c;
			}

			:host {
				--gl-icon-size: 1.6rem;

				display: inline-block;
				width: 16px;
				aspect-ratio: 1 / 1;
			}

			:host([conflict]) {
				--gl-icon-size: 2.2rem;
				margin-right: 0.4rem;

				width: 22px;
				aspect-ratio: auto;
			}

			svg {
				display: inline-block;
				vertical-align: text-bottom;
			}
		`,
	];

	@property()
	status?: GitFileStatus | 'T';

	@state()
	get statusName(): string {
		if (!this.status) return '';
		return getGitFileStatusText(this.status);
	}

	override updated(changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void {
		super.updated(changedProperties);
		if (changedProperties.has('status')) {
			if (this.statusName) {
				this.setAttribute('title', this.statusName);
			} else {
				this.removeAttribute('title');
			}

			if (this.status?.length === 2) {
				this.setAttribute('conflict', '');
			} else {
				this.removeAttribute('conflict');
			}
		}
	}

	private renderIgnored() {
		return html`
			<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" viewBox="0 0 16 16">
				<path
					fill="#969696"
					fill-rule="evenodd"
					d="M7.5 15a7.5 7.5 0 1 0 0-15 7.5 7.5 0 0 0 0 15zM10 4l-6.01 6.01 1.06 1.061 6.01-6.01L10 4z"
					clip-rule="evenodd"
				/>
			</svg>
		`;
	}

	private renderUntracked() {
		return html`
			<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" viewBox="0 0 16 16">
				<path
					fill="#6C6C6C"
					fill-rule="evenodd"
					d="M7.5 15a7.5 7.5 0 1 0 0-15 7.5 7.5 0 0 0 0 15zm-3.942-3.942l7.5-7.5.884.884-.664.664c.95.655 1.65 1.524 2.222 2.394-1.15 1.75-2.824 3.5-6 3.5-.696 0-1.32-.084-1.882-.234l-1.176 1.176-.884-.884zm5.188-3.42l1.629-1.629c.634.393 1.147.913 1.594 1.491C10.99 8.767 9.692 9.75 7.5 9.75c-.287 0-.56-.017-.817-.05l.455-.454a1.5 1.5 0 0 0 1.608-1.608zM7.362 6.254L5.754 7.862a1.5 1.5 0 0 1 1.608-1.608zm.955-.955A6.595 6.595 0 0 0 7.5 5.25c-2.192 0-3.49.982-4.469 2.25.447.578.96 1.098 1.594 1.491l-.903.903C2.772 9.239 2.072 8.369 1.5 7.5 2.65 5.75 4.324 4 7.5 4c.696 0 1.32.084 1.882.234L8.317 5.299z"
					clip-rule="evenodd"
				/>
			</svg>
		`;
	}

	private renderAdded() {
		return html`
			<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" viewBox="0 0 16 16">
				<path
					fill="#388A34"
					fill-rule="evenodd"
					d="M7.5 15a7.5 7.5 0 1 0 0-15 7.5 7.5 0 0 0 0 15zm.75-6.75h3v-1.5h-3v-3h-1.5v3h-3v1.5h3v3h1.5v-3z"
					clip-rule="evenodd"
				/>
			</svg>
		`;
	}

	private renderDeleted() {
		return html`
			<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" viewBox="0 0 16 16">
				<path
					fill="#9E121D"
					fill-rule="evenodd"
					d="M7.5 15a7.5 7.5 0 1 0 0-15 7.5 7.5 0 0 0 0 15zm3.75-6.75v-1.5h-7.5v1.5h7.5z"
					clip-rule="evenodd"
				/>
			</svg>
		`;
	}

	private renderModified() {
		return html`
			<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" viewBox="0 0 16 16">
				<path
					fill="#1B80B2"
					fill-rule="evenodd"
					d="M7.5 15a7.5 7.5 0 1 0 0-15 7.5 7.5 0 0 0 0 15zm3.75-9.5V7h-3v2.5h-1.5V7h-3V5.5h3v-3h1.5v3h3zm0 5V12h-7.5v-1.5h7.5z"
					clip-rule="evenodd"
				/>
			</svg>
		`;
	}

	private renderRenamed() {
		return html`
			<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" viewBox="0 0 16 16">
				<path
					fill="#C63"
					fill-rule="evenodd"
					d="M7.5 15a7.5 7.5 0 1 0 0-15 7.5 7.5 0 0 0 0 15zM9.25 4.5v1.25h1.25l1 1v2.5l-1 1H9.25v1.25H10v1.25H7V11.5h.75v-1.25H4l-1-1v-2.5l1-1h3.75V4.5H7V3.25h3V4.5h-.75zm-5 2.5h3.5v2h-3.5V7zm5 0v2h1V7h-1z"
					clip-rule="evenodd"
				/>
			</svg>
		`;
	}

	private renderCopied() {
		return html`
			<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" viewBox="0 0 16 16">
				<path
					fill="#692C77"
					fill-rule="evenodd"
					d="M7.5 15a7.5 7.5 0 1 0 0-15 7.5 7.5 0 0 0 0 15zM6.964 3.75L5.893 4.813v.53h1.071v-.53h3.215v4.25h-.536v1.062h.536l1.071-1.063v-4.25L10.179 3.75H6.964zM3.75 6.938l1.071-1.063h3.215l1.071 1.063v4.25L8.036 12.25H4.82L3.75 11.187v-4.25zm1.071 0v4.25h3.215v-4.25H4.82z"
					clip-rule="evenodd"
				/>
			</svg>
		`;
	}

	private renderConflictGlyphs(
		leftColor: string,
		leftGlyph: string,
		leftFg: string,
		rightColor: string,
		rightGlyph: string,
		rightFg: string,
	) {
		// 22x16 split icon: two halves with 2px gap, rounded outer edges (r=3), flat inner edges
		return html`
			<svg xmlns="http://www.w3.org/2000/svg" width="22" height="16" fill="none" viewBox="0 0 22 16">
				<path d="M3 0H10V16H3C1.35 16 0 14.65 0 13V3C0 1.35 1.35 0 3 0Z" fill="${leftColor}" />
				<path d="M12 0H19C20.65 0 22 1.35 22 3V13C22 14.65 20.65 16 19 16H12V0Z" fill="${rightColor}" />
				<text
					x="5"
					y="7"
					dominant-baseline="central"
					text-anchor="middle"
					font-size="12"
					font-weight="700"
					fill="${leftFg}"
				>
					${leftGlyph}
				</text>
				<text
					x="17"
					y="7"
					dominant-baseline="central"
					text-anchor="middle"
					font-size="12"
					font-weight="700"
					fill="${rightFg}"
				>
					${rightGlyph}
				</text>
			</svg>
		`;
	}

	private renderConflictUU() {
		const m = 'var(--gl-git-status-conflict-modified, #c4a000)';
		return this.renderConflictGlyphs(m, '±', '#000', m, '±', '#000');
	}

	private renderConflictAA() {
		const a = 'var(--gl-git-status-added)';
		return this.renderConflictGlyphs(a, '+', '#fff', a, '+', '#fff');
	}

	private renderConflictDD() {
		const d = 'var(--gl-git-status-deleted)';
		return this.renderConflictGlyphs(d, '−', '#fff', d, '−', '#fff');
	}

	private renderConflictDU() {
		return this.renderConflictGlyphs(
			'var(--gl-git-status-deleted)',
			'−',
			'#fff',
			'var(--gl-git-status-conflict-modified, #c4a000)',
			'±',
			'#000',
		);
	}

	private renderConflictUD() {
		return this.renderConflictGlyphs(
			'var(--gl-git-status-conflict-modified, #c4a000)',
			'±',
			'#000',
			'var(--gl-git-status-deleted)',
			'−',
			'#fff',
		);
	}

	private renderConflictAU() {
		return this.renderConflictGlyphs(
			'var(--gl-git-status-added)',
			'+',
			'#fff',
			'var(--gl-git-status-conflict-modified, #c4a000)',
			'±',
			'#000',
		);
	}

	private renderConflictUA() {
		return this.renderConflictGlyphs(
			'var(--gl-git-status-conflict-modified, #c4a000)',
			'±',
			'#000',
			'var(--gl-git-status-added)',
			'+',
			'#fff',
		);
	}

	private renderUnknown() {
		return html`
			<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" viewBox="0 0 16 16">
				<path
					fill="#6C6C6C"
					fill-rule="evenodd"
					d="M7.5 15a7.5 7.5 0 1 0 0-15 7.5 7.5 0 0 0 0 15zM9.19 2.822c-.439-.215-.97-.322-1.596-.322-1.25 0-2.282.478-3.094 1.435l1.05.798c.275-.331.579-.574.91-.728.331-.154.66-.231.987-.231.415 0 .76.093 1.036.28.275.182.413.448.413.798 0 .275-.082.509-.245.7-.159.187-.36.364-.602.532a9.506 9.506 0 0 0-.728.56 2.66 2.66 0 0 0-.602.763c-.159.299-.238.679-.238 1.141v.483h1.498v-.413c0-.364.086-.663.259-.896a2.76 2.76 0 0 1 .637-.616c.252-.177.504-.362.756-.553.257-.196.471-.436.644-.721.173-.285.259-.651.259-1.099 0-.387-.114-.749-.343-1.085-.229-.34-.562-.616-1.001-.826zm-1.169 7.917a1.024 1.024 0 0 0-.763-.315c-.294 0-.544.105-.749.315-.2.205-.301.453-.301.742 0 .294.1.546.301.756.205.205.455.308.749.308.303 0 .558-.103.763-.308.205-.21.308-.462.308-.756 0-.29-.103-.537-.308-.742z"
					clip-rule="evenodd"
				/>
			</svg>
		`;
	}

	override render(): unknown {
		switch (this.status) {
			case '!':
				return this.renderIgnored();
			case '?':
				return this.renderUntracked();
			case 'A':
				return this.renderAdded();
			case 'D':
				return this.renderDeleted();
			case 'M':
			case 'T':
			case 'U':
				return this.renderModified();
			case 'R':
				return this.renderRenamed();
			case 'C':
				return this.renderCopied();
			case 'AA':
				return this.renderConflictAA();
			case 'AU':
				return this.renderConflictAU();
			case 'UA':
				return this.renderConflictUA();
			case 'DD':
				return this.renderConflictDD();
			case 'DU':
				return this.renderConflictDU();
			case 'UD':
				return this.renderConflictUD();
			case 'UU':
				return this.renderConflictUU();
		}

		return this.renderUnknown();
	}
}
