import { CanvasSmbl } from '../infrastructure/canvas-smbl.js';
import { pointInCanvas } from '../infrastructure/move-scale-applay.js';
import { listen } from '../infrastructure/util.js';
import { tipShow } from './ui.js';

export class ShapeMenu extends HTMLElement {
	connectedCallback() {
		const shadow = this.attachShadow({ mode: 'closed' });
		shadow.innerHTML =
			`<style>
			.menu {
                position: absolute !important;
				overflow-x: auto;
				padding: 0;
				top: 50%;
				left: 13px;
				transform: translateY(-50%);
				box-shadow: 0px 0px 58px 2px rgba(34, 60, 80, 0.2);
				border-radius: 16px;
				background-color: rgba(255,255,255, .9);
			}

			.content {
				white-space: nowrap;
				display: flex;
				flex-direction: column;
			}
			
			[data-cmd] {
				cursor: pointer;
			}

			.menu svg { padding: 10px; }
			.stroke {
				stroke: #344767;
				stroke-width: 2px;
				fill: transparent;
			}
		
			.menu .big {
				width: 62px;
				min-width: 62px;
			}

			@media only screen and (max-width: 700px) {
				.menu {
					width: 100%;
					border-radius: 0;
					bottom: 0;
					display: flex;
  					flex-direction: column;
					top: unset;
					left: unset;
					transform: unset;
				}

				.content {
					align-self: center;
					flex-direction: row;
				}
			}
			</style>
			<div id="menu" class="menu" style="touch-action: none;">
				<div class="content">
					<svg class="stroke" data-cmd="shapeAdd" data-cmd-arg="1" viewBox="0 0 24 24" width="24" height="24"><circle r="9" cx="12" cy="12"></circle></svg>
					<svg class="stroke" data-cmd="shapeAdd" data-cmd-arg="4" viewBox="0 0 24 24" width="24" height="24"><path d="M2 12 L12 2 L22 12 L12 22 Z" stroke-linejoin="round"></path></svg>
					<svg class="stroke" data-cmd="shapeAdd" data-cmd-arg="2" viewBox="0 0 24 24" width="24" height="24"><rect x="2" y="4" width="20" height="16" rx="3" ry="3"></rect></svg>
					<svg data-cmd="shapeAdd" data-cmd-arg="0" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M13 8v8a3 3 0 0 1-3 3H7.83a3.001 3.001 0 1 1 0-2H10a1 1 0 0 0 1-1V8a3 3 0 0 1 3-3h3V2l5 4-5 4V7h-3a1 1 0 0 0-1 1z" fill="rgba(52,71,103,1)"/></svg>
					<svg data-cmd="shapeAdd" data-cmd-arg="3" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M13 6v15h-2V6H5V4h14v2z" fill="rgba(52,71,103,1)"/></svg>
				</div>
			</div>`;

		const menu = shadow.getElementById('menu');
		menu.querySelectorAll('[data-cmd="shapeAdd"]').forEach(el => listen(el, 'pointerdown', this));
		listen(menu, 'pointerleave', this);
		listen(menu, 'pointerup', this);
		listen(menu, 'pointermove', this);
	};

	/** @param {CanvasElement} canvas */
	init(canvas) {
		/** @private */ this._canvas = canvas;
	}

	/** @param {PointerEvent & { currentTarget: Element }} evt */
	handleEvent(evt) {
		switch (evt.type) {
			case 'pointermove':
				if (!this._isNativePointerleaveTriggered) {
					// emulate pointerleave for mobile

					const pointElem = document.elementFromPoint(evt.clientX, evt.clientY);
					if (pointElem === this._pointElem) {
						return;
					}

					// pointerleave
					if (this._parentElem === this._pointElem) {
						// TODO: check mobile
						this._canvas.ownerSVGElement.setPointerCapture(evt.pointerId);
					}

					/**
					 * @type {Element}
					 * @private
					 */
					this._pointElem = pointElem;
				}
				break;
			case 'pointerleave':
				this._isNativePointerleaveTriggered = true;
				if (this._pressedShapeTemplKey != null) {
					// when shape drag out from menu panel
					this._shapeCreate(evt);
				}
				this._clean();
				break;
			case 'pointerdown':
				this._pressedShapeTemplKey = parseInt(evt.currentTarget.getAttribute('data-cmd-arg'));

				// for emulate pointerleave
				this._parentElem = document.elementFromPoint(evt.clientX, evt.clientY);
				this._pointElem = this._parentElem;
				this._isNativePointerleaveTriggered = null;
				break;
			case 'pointerup':
				this._clean();
				break;
		}
	}

	/**
	 * @param {PointerEvent} evt
	 * @private
	 */
_shapeCreate(evt) {
    tipShow(false);
    if (this._pressedShapeTemplKey == null) return;

    const svg = this._canvas.ownerSVGElement;
    const pt = svg.createSVGPoint();
    pt.x = evt.clientX; pt.y = evt.clientY;
    const loc = pt.matrixTransform(this._canvas.getScreenCTM().inverse());
    const x = loc.x, y = loc.y;

    let shapeData;
    if (this._pressedShapeTemplKey === 0) {
        shapeData = {
            s: { data: { dir: 'right', position: { x: x - 24, y } } },
            e: { data: { dir: 'right', position: { x: x + 24, y } } }
        };
    } else {
        shapeData = {
            type: this._pressedShapeTemplKey,
            position: { x, y },
            title: 'Title'
        };
    }

    const shapeEl = this._canvas[CanvasSmbl].shapeMap[this._pressedShapeTemplKey].create(shapeData);
    this._canvas.append(shapeEl);

    // Для стрелки и других форм диспатчим pointerdown
    shapeEl.dispatchEvent(new PointerEvent('pointerdown', evt));

    // transform ставим только для фигур, которые не path
    if (this._pressedShapeTemplKey !== 0) {
        shapeEl.setAttribute('transform', `translate(${x},${y})`);
    }
}


	/** @private */
	_clean() {
		this._pressedShapeTemplKey = null;
		this._parentElem = null;
		this._pointElem = null;
	}
}
customElements.define('ap-menu-shape', ShapeMenu);

/** @typedef { import('../shapes/shape-type-map.js').ShapeType } ShapeType */
/** @typedef { import('../infrastructure/canvas-smbl.js').CanvasElement } CanvasElement */
