import Clutter from 'gi://Clutter';
import GObject from 'gi://GObject';

import { gettext as _ } from 'resource:///org/gnome/shell/extensions/extension.js';

import { registerClass } from '../../common/gjs.js';
import { Icon } from '../../common/icons.js';
import { CodeLabel } from '../components/codeLabel.js';
import { CodeInfo } from '../components/contentInfo.js';
import { ClipboardItem } from './clipboardItem.js';

var __decorate =
	(this && this.__decorate) ||
	function (decorators, target, key, desc) {
		var c = arguments.length,
			r = c < 3 ? target : desc === null ? (desc = Object.getOwnPropertyDescriptor(target, key)) : desc,
			d;
		if (typeof Reflect === 'object' && typeof Reflect.decorate === 'function')
			r = Reflect.decorate(decorators, target, key, desc);
		else
			for (var i = decorators.length - 1; i >= 0; i--)
				if ((d = decorators[i])) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
		return (c > 3 && r && Object.defineProperty(target, key, r), r);
	};

let CodeItem = class CodeItem extends ClipboardItem {
	codeItemSettings;
	_code;
	_codeInfo;

	constructor(ext, entry) {
		super(ext, entry, Icon.Code, _('Code'));
		this.codeItemSettings = this.ext.settings.get_child('code-item');
		this.add_style_class_name('code-item');
		const metadata = { language: null, ...entry.metadata };
		this._code = new CodeLabel(ext, {
			style_class: 'code-item-content',
			language: metadata.language,
			y_align: Clutter.ActorAlign.FILL,
			y_expand: true,
		});
		this._content.add_child(this._code);
		this.codeItemSettings.connectObject(
			'changed::syntax-highlighting',
			this.updateCode.bind(this),
			'changed::show-line-numbers',
			this.updateCode.bind(this),
			'changed::show-code-info',
			this.updateCodeInfo.bind(this),
			'changed::text-count-mode',
			this.updateCodeInfo.bind(this),
			this,
		);
		this.ext.settings.connectObject('changed::tab-width', this.updateCode.bind(this), this._code);

		// Update label
		this.entry.bind_property('content', this._code, 'code', GObject.BindingFlags.SYNC_CREATE);
		this.entry.connect('notify::content', this.updateCodeInfo.bind(this));
		this.entry.connect('notify::metadata', () => {
			const m = { language: null, ...this.entry.metadata };
			this._code.language = m.language;
			if (this._codeInfo) this._codeInfo.language = m.language?.name ?? null;
		});
		this.updateCode();
		this.updateCodeInfo();

		// Update metadata
		this._code.connect('notify::language', () => {
			this.entry.metadata = { language: this._code.language };
		});
	}

	updateCode() {
		this._code.syntaxHighlighting = this.codeItemSettings.get_boolean('syntax-highlighting');
		this._code.showLineNumbers = this.codeItemSettings.get_boolean('show-line-numbers');
		this._code.tabWidth = this.ext.settings.get_int('tab-width');
	}

	updateCodeInfo() {
		const show = this.codeItemSettings.get_boolean('show-code-info');
		const textCountMode = this.codeItemSettings.get_enum('text-count-mode');
		if (this._codeInfo) {
			this._codeInfo.visible = show;
			this._codeInfo.text = this.entry.content;
			this._codeInfo.textCountMode = textCountMode;
		} else if (show) {
			const m = { language: null, ...this.entry.metadata };
			this._codeInfo = new CodeInfo(this.entry.content, textCountMode, m.language?.name ?? null);
			this._content.add_child(this._codeInfo);
		}
	}

	destroy() {
		this.codeItemSettings.disconnectObject(this);
		this.ext.settings.disconnectObject(this._code);
		super.destroy();
	}
};
CodeItem = __decorate([registerClass()], CodeItem);

export { CodeItem };
