import Sqids from "sqids";
import { writable, Writable } from "svelte/store";
import { ZodEffects, ZodNullable, ZodOptional, ZodType } from "zod";

/**
 * Synchronisiert den ersten Writable in den zweiten.
 */
export function writableSync<T>(source: Writable<T>) {
	let $val;
	source.subscribe($ => $val = $)();
	const target = writable<T>($val)

	source.subscribe((value) => {
		target.set(value);
	})

	return target;
}

export function localStorageSync<T>(initial: T, name: string, modifier: (stored: any) => T = (stored) => stored, reverseModifier: (value: T) => string = (value) => value as string): Writable<T> {
	const stored = localStorage.getItem(name) as T
	let value = initial;
	if (stored) {
		value = modifier(stored)
	}

	const writableStore = writable(value)

	writableStore.subscribe((value) => {
		const reversed = reverseModifier(value);
		localStorage.setItem(name, reversed)
	})

	return writableStore
}

export function isZodInstanceOf<T extends ZodType<any>>(
  schema: ZodType<any>,
  targetType: new (...args: any) => T
): schema is T {
  if (schema instanceof targetType) {
    return true;
  }

  if (schema instanceof ZodOptional || schema instanceof ZodNullable) {
    return isZodInstanceOf(schema._def.innerType, targetType);
  }else if (schema instanceof ZodEffects) {
		return isZodInstanceOf(getZodBaseType(schema._def.schema), targetType)
	}

  return false;
}

export function getZodBaseType(schema: ZodType<any>): ZodType<any> {
  if (schema instanceof ZodOptional || schema instanceof ZodNullable) {
    return getZodBaseType(schema._def.innerType);
  } else if (schema instanceof ZodEffects) {
		return getZodBaseType(schema._def.schema)
	}
  return schema;
}