import { useNavigate, useParams } from "@solidjs/router";
import { Component, Show, createEffect, createSignal } from "solid-js";

import styles from './GroupPage.module.css'
import { Group, Map, Profile, Strat, User, api } from "../api";
import { showDialog, showInputDialog, showMessageDialog } from "../state";
import { _arrayBufferToBase64, errorToString, normalize } from "../util";
import { BsCheck2, BsPencil, BsTrash } from "solid-icons/bs";
import { Collapse } from "solid-collapse";
import MemberItem from "../components/MemberItem";
import MapItem from "../components/MapItem";
import StratItem from "../components/StratItem";
import StratTypeItem from "../components/StratTypeItem";
import ProfileItem from "../components/ProfileItem";
import { UploadFile, createFileUploader } from "@solid-primitives/upload";

const GroupPage: Component = () => {
	const params = useParams();
	const navigate = useNavigate();

	const [loading, setLoading] = createSignal(true);
	const [group, setGroup] = createSignal({} as Group);
	const [editing, setEditing] = createSignal(false);
	const [name, setName] = createSignal('');

	const [membersIsExpanded, setMembersIsExpanded] = createSignal(false);
	const [mapsIsExpanded, setMapsIsExpanded] = createSignal(false);
	const [stratsIsExpanded, setStratsIsExpanded] = createSignal(false);
	const [profilesIsExpanded, setProfilesIsExpanded] = createSignal(false);
	const [stratTypesIsExpanded, setStratTypesIsExpanded] = createSignal(false);

	createEffect(async () => {
		try {
			setGroup(await api().getGroup(params.id));
			setName(group().name);
			setLoading(false);
		} catch (e) {
			showMessageDialog('Failed to load group', errorToString(e));
		}
	}, []);

	const updateGroup = async (newValue: Group) => {
		try {
			await api().updateGroup(group().id, newValue);
			setGroup(newValue);
		} catch (e) {
			showMessageDialog('Failed to update group', errorToString(e));
		}
	};

	const deleteGroup = async () => {
		showDialog({
			title: 'Delete group',
			text: 'Do you want to delete this group?',
			buttons: [
				{
					name: 'Delete',
					type: 'danger',
					action: async () => {
						try {
							await api().removeGroup(group().id);
							navigate('/groups');
						} catch (e) {
							showMessageDialog('Failed to delete group', errorToString(e));
						}
					}
				},
				{
					name: 'Cancel',
					action: () => { }
				}
			]
		});
	};

	const addMember = async () => {
		showInputDialog('Add member to Group', 'enter the member id you want to add', 'member ID', async (memberId) => {
			try {
				const newGroup = await api().addMember(group().id, memberId);
				setGroup(newGroup);
			} catch (e) {
				showMessageDialog('Failed to add member', errorToString(e));
			}
		})
	};

	const addStratType = async () => {
		showInputDialog('Add strat type to Group', 'enter the name you want to add', 'strat type', async (stratType) => {
			try {
				const newGroup = await api().addStratType(group().id, stratType);
				setGroup(newGroup);
			} catch (e) {
				showMessageDialog('Failed to add strat type', errorToString(e));
			}
		})
	};

	const addProfile = async () => {
		const [profileName, setProfileName] = createSignal('');
		const { files, selectFiles } = createFileUploader({
			multiple: false,
			accept: "image/*",
		});

		let fileReader = new FileReader();

		fileReader.onload = async event => {
			try {
				const newGroup = await api().addProfileToGroup(group().id, { name: profileName(), image: _arrayBufferToBase64(event.target!.result as ArrayBuffer) });
				setGroup(newGroup);
			} catch (e) {
				showMessageDialog('Failed to add profile', errorToString(e));
			}
		}

		showDialog({
			title: 'Add profile to Group',
			text: 'create a new profile',
			inputFields: [{
				onInput: setProfileName,
				placeholder: 'name'
			}],
			onDismiss: async () => {
				fileReader.readAsArrayBuffer(files()[0].file);
			},
			buttons: [{
				name: 'add image', action: () => selectFiles(([{ source, name, size, file }]) => {
					console.log({ source, name, size, file });
				}),
				closeOnClick: false
			},
				'confirm'
			],
		})
	};

	const toggleEdit = async () => {
		if (!editing()) {
			setEditing(true);
		} else {
			console.log(name());
			updateGroup({ ...group(), name: name() });
			setEditing(false);
		}
	};

	const onDeleteMember = async (member: User) => {
		setGroup({ ...group(), members: [...group().members.filter(m => m.username !== member.username)] });
	};

	const onDeleteMap = async (map: Map) => {
		setGroup({ ...group(), maps: [...group().maps.filter(m => m.id !== map.id)] });
	};

	const onDeleteStrat = async (strat: Strat) => {
		setGroup({ ...group(), strats: [...group().strats.filter(s => s.id !== strat.id)] });
	};

	const onDeleteStratType = async (stratType: string) => {
		setGroup({ ...group(), stratTypes: [...group().stratTypes.filter(s => s !== stratType)] });
	};

	const onDeleteProfile = async (profile: Profile) => {
		setGroup({ ...group(), profiles: [...group().profiles.filter(p => p.id !== profile.id)] });
	};

	return (
		<>
			<Show when={!loading()} fallback={<div>Loading...</div>}>
				<div class={styles.groupName}>
					<span contentEditable={editing()} innerText={group().name} onInput={e => setName(normalize(e.currentTarget.innerText, 50, true))} />
					{editing() && <span class={styles.editCount}>{name().length}/50</span>}
				</div>
				<div class={styles.groupButtons}>
					<button class={styles.deleteButton} onClick={deleteGroup}>Delete group</button>
					<button class={styles.editButton} onClick={toggleEdit}>{editing() ? <BsCheck2 /> : <BsPencil />}</button>
				</div>
				<hr />
				<div>
					<button onClick={() => setMembersIsExpanded(!membersIsExpanded())}>Members</button>
					<button class={styles.addMemberButton} onClick={addMember}>+</button>
					<Collapse value={membersIsExpanded()} class={styles.members}>
						<div class={styles.groupMembers}>
							{group().members?.map(m => <MemberItem group={group()} member={m} onDelete={onDeleteMember} />)}
						</div>
					</Collapse>
					<br />
					<button onClick={() => setStratsIsExpanded(!stratsIsExpanded())}>strats</button>
					<Collapse value={stratsIsExpanded()} class={styles.strats}>
						<div class={styles.strats}>
							{group().strats?.map(s => <StratItem group={group()} strat={s} onDelete={onDeleteStrat} />)}
						</div>
					</Collapse>
					<br />
					<button onClick={() => setMapsIsExpanded(!mapsIsExpanded())}>maps</button>
					<Collapse value={mapsIsExpanded()} class={styles.maps}>
						<div class={styles.maps}>
							{group().maps?.map(m => <MapItem group={group()} map={m} onDelete={onDeleteMap} />)}
						</div>
					</Collapse>
					<br />
					<button onClick={() => setStratTypesIsExpanded(!stratTypesIsExpanded())}>strat types</button>
					<button class={styles.addMemberButton} onClick={addStratType}>+</button>
					<Collapse value={stratTypesIsExpanded()} class={styles.stratTypes}>
						<div class={styles.stratTypes}>
							{group().stratTypes?.map(s => <StratTypeItem group={group()} stratType={s} onDelete={onDeleteStratType} />)}
						</div>
					</Collapse>
					<br />
					<button onClick={() => setProfilesIsExpanded(!profilesIsExpanded())}>profiles</button>
					<button class={styles.addMemberButton} onClick={addProfile}>+</button>
					<Collapse value={profilesIsExpanded()} class={styles.profiles}>
						<div class={styles.profiles}>
							{group().profiles?.map(p => <ProfileItem group={group()} profile={p} onDelete={onDeleteProfile} />)}
						</div>
					</Collapse>
				</div>
			</Show>
		</>
	)
}

export default GroupPage;
