import { LitElement, css, html } from 'lit';
import { customElement, query } from 'lit/decorators.js';

import '@shoelace-style/shoelace/dist/components/card/card.js';

import '@shoelace-style/shoelace/dist/components/button/button.js';

import { styles } from '../../styles/shared-styles';


import {EditorState} from 'prosemirror-state'
import { Transaction } from 'prosemirror-state';
import { EditorView } from 'prosemirror-view';
import { Schema } from 'prosemirror-model';

import { MenuBar } from './write-menu';
import { keymap } from 'prosemirror-keymap';
import { toggleMark } from 'prosemirror-commands';
import {undo, redo, history} from 'prosemirror-history'
import { baseKeymap } from 'prosemirror-commands';



export const customSchema = new Schema({
	nodes: {
	  text: {
		group: 'inline',
	  },
	  star: {
		inline: true,
		group: 'inline',
		toDOM() {
		  return ['star', '⭐'];
		},
		parseDOM: [{ tag: 'star' }],
	  },
	  paragraph: {
		group: 'block',
		content: 'inline*',
		toDOM() {
		  return ['p', 0];
		},
		parseDOM: [{ tag: 'p' }],
	  },
	  boring_paragraph: {
		group: 'block',
		content: 'text*',
		marks: '',
		toDOM() {
		  return ['p', { class: 'boring' }, 0];
		},
		parseDOM: [{ tag: 'p.boring', priority: 60 }],
	  },
	  doc: {
		content: 'block+',
	  },
	},
	marks: {
	  shouting: {
		toDOM() {
		  return ['shouting', 0];
		},
		parseDOM: [{ tag: 'shouting' }],
	  },
	  link: {
		attrs: { href: {} },
		toDOM(node) {
		  return ['a', { href: node.attrs.href }, 0];
		},
		parseDOM: [
		  {
			tag: 'a',
			getAttrs(dom) {
			  return { href: dom };
			},
		  },
		],
		inclusive: false,
	  },
	},
  });

  // function for error reports

  function errorReport(message: string): void {
	console.error(message);
  }


  // Commands
function insertStar(state: EditorState, dispatch?: (tr: Transaction) => void): boolean {
	const type = customSchema.nodes.star;
	const { $from } = state.selection;

	// If the parent cannot replace with the 'star' node, return false
	if (!$from.parent.canReplaceWith($from.index(), $from.index(), type)) {
	  return false;
	}

	// If dispatch is provided, apply the transaction
	if (dispatch) {
	  dispatch(state.tr.replaceSelectionWith(type.create()));
	}

	// Always return true if insertion conditions are met
	return true;
  }

/* this command will prompt you for a url, which will
apply link mark to your selection and make your selection a hyperlink  */


function toggleLink(state: EditorState, dispatch?: (tr: Transaction) => void): boolean {
	let {doc, selection} = state
	if (selection.empty) return false
	let attrs = null
	if (!doc.rangeHasMark(selection.from, selection.to, customSchema.marks.link)) {
	  attrs = {href: prompt("Link to where?", "")}
	  if (!attrs.href) return false
	}
	return toggleMark(customSchema.marks.link, attrs)(state, dispatch)
  }


 /*  starting to  build a function that inserts an <hr> line break

 function insertHR(state: EditorState, dispatch?: (tr: Transaction) => void): boolean {
	const type = customSchema.nodes.boring_paragraph
	return false
  } */


  // custom keymap to apply to state
const customKeymap = keymap({
	'Ctrl-Space': insertStar,
	'Ctrl-b': (state, dispatch) => {
    console.log("Ctrl-b pressed, toggling shouting mark...");
    return toggleMark(customSchema.marks.shouting)(state, dispatch);
  },
  	'Ctrl-q': (state, dispatch) => {
		console.log("you should have just gotten an alert");
		return toggleLink(state, dispatch);
	},


  });


  const menuItems = [
  {
    label: 'Bold',
    command: (state, dispatch, view) => {
      // Example command logic for bold
      console.log('Bold clicked');
      return true; // Return true if active, false otherwise
    },
  },
  {
    label: 'Italic',
    command: (state, dispatch, view) => {
      console.log('Italic clicked');
      return true;
    },
  },
];



@customElement('app-write')
export class AppWrite extends LitElement {

	// references the class name of the container that prosemirror's editor
	// will render to
	@query('.ProseMirror') editorContainer!: HTMLElement;

	private editorView!: EditorView

    static styles = [
        styles,
	css`
		.ProseMirror {
			position: relative;
			white-space: pre-wrap;
			word-wrap: break-word;
			outline: none;
			background-color: white;
			color: black;
			border-radius: 4px;
			padding: 10px;
			min-height: 200px; /* Ensure there's enough height to type */
			}

		.ProseMirror:empty::before {
			content: "Start typing here...";
			color: black;
				pointer-events: none; /* Ensures the placeholder doesn't block typing */

		}



		.ProseMirror {
			word-wrap: break-word;
			white-space: pre-wrap;
			white-space: break-spaces;
			-webkit-font-variant-ligatures: none;
			font-variant-ligatures: none;
			font-feature-settings: "liga" 0; /* the above doesn't seem to work in Edge */
			}

		.ProseMirror pre {
			white-space: pre-wrap;
			}

		.ProseMirror li {
			position: relative;
			}

			.ProseMirror-hideselection *::selection { background: transparent; }
			.ProseMirror-hideselection *::-moz-selection { background: transparent; }
			.ProseMirror-hideselection { caret-color: transparent; }

			/* See https://github.com/ProseMirror/prosemirror/issues/1421#issuecomment-1759320191 */
			.ProseMirror [draggable][contenteditable=false] { user-select: text }

			.ProseMirror-selectednode {
			outline: 2px solid #8cf;
			}

			/* Make sure li selections wrap around markers */

			li.ProseMirror-selectednode {
			outline: none;
			}

			li.ProseMirror-selectednode:after {
			content: "";
			position: absolute;
			left: -32px;
			right: -2px; top: -2px; bottom: -2px;
			border: 2px solid #8cf;
			pointer-events: none;
			}

			/* Protect against generic img rules */

			img.ProseMirror-separator {
			display: inline !important;
			border: none !important;
			margin: 0 !important;
			}

			shouting {
			all: unset; /* Remove inherited or conflicting styles */
			font-weight: bold;
			text-transform: uppercase;
			color: red;
			}

			`
    	];


		protected async firstUpdated() {
			console.log("Welcome to the compose page");
			await this.updateComplete;
			console.log('Rendered HTML:', this.shadowRoot?.innerHTML);

			this.initializeEditor()
			if (!this.editorContainer) {
				errorReport('Editor container not here');
				return;
			}
		}

		private initializeEditor() {

			if (!this.editorContainer) {
			errorReport('Editor container not here');
				return;
			}

		/*  this is a schema of initial content to pre-populate the  */

		const initialContent = customSchema.nodes.doc.createAndFill([
			customSchema.nodes.paragraph.create(
		  	null,
		  	customSchema.text("Welcome to the editor! Start typing here.")
				)]);


		if (!initialContent) {
			console.error("failed to create initial document")
			return;
			}

		const state = EditorState.create({
    		doc: initialContent,
    		plugins: [
				history(),
      			keymap({
        		'Mod-z': undo,
        		'Mod-y': redo,
      			}),
				  customKeymap,
      			keymap(baseKeymap),
    			],
	 		});



		let view = new EditorView(this.editorContainer, {
			state,
			dispatchTransaction(transaction) {
				console.log('Document size went from', transaction.before.content.size, "to",
					transaction.doc.content.size
				)
				let newState = view.state.apply(transaction)
				view.updateState(newState)
			}
			});





	}

	connectedCallback(): void {
		super.connectedCallback();

		console.log('AppWrite added to the DOM')
	}

    disconnectedCallback(): void {
        super.disconnectedCallback();
		if (this.editorView) {
			this.editorView.destroy();
			this.editorView = null!
		}
    }



    protected render() {
        return html`
        <app-header ?enableBack="${true}"></app-header>

		<main>

	<div class="ProseMirror"></div>

            </main>
        `;
	}
}