//
// .keyman-touch-layout JSON format
//
// Follows /common/schemas/keyman-touch-layout/keyman-touch-layout.spec.json for
// reading and
// /common/schemas/keyman-touch-layout/keyman-touch-layout.clean.spec.json for
// writing
//

/**
 * On screen keyboard description consisting of specific layouts for tablet, phone,
 * and desktop. Despite its name, this format is used for both touch layouts and
 * hardware-style layouts.
 */
export interface TouchLayoutFile {
  tablet?: TouchLayoutPlatform;
  phone?: TouchLayoutPlatform;
  desktop?: TouchLayoutPlatform;
};

export type TouchLayoutFont = string;
export type TouchLayoutFontSize = string;
export type TouchLayoutDefaultHint = "none"|"dot"|"longpress"|"multitap"|"flick"|"flick-n"|"flick-ne"|"flick-e"|"flick-se"|"flick-s"|"flick-sw"|"flick-w"|"flick-nw";

/** touch layout specification for a specific platform like phone or tablet */
export interface TouchLayoutPlatform {
  font?: TouchLayoutFont;
  fontsize?: TouchLayoutFontSize;
  layer: TouchLayoutLayer[];
  displayUnderlying?: boolean;
  defaultHint: TouchLayoutDefaultHint;
};

export type TouchLayoutLayerId = string;  // pattern = /^[a-zA-Z0-9_-]+$/

/** a layer with rows of keys on a touch layout */
export interface TouchLayoutLayer {
  id: TouchLayoutLayerId;
  row: TouchLayoutRow[];
};

export type TouchLayoutRowId = number;

/** a row of keys on a touch layout */
export interface TouchLayoutRow {
  id: TouchLayoutRowId;
  key: TouchLayoutKey[];
};

type Key_Type = 'T'|'K'|'U'|'t'|'k'|'u';
type Key_Id = string;

export type TouchLayoutKeyId = `${Key_Type}_${Key_Id}`; // pattern = /^[TKUtku]_[a-zA-Z0-9_]+$/

/**
 * Denotes private-use identifiers that should be considered 'reserved'.
 */
export const PRIVATE_USE_IDS = [
  /**
   * Private-use identifiers used by KeymanWeb for the default multitap-into-caps-layer key
   * for keyboards with a caps layer while not defining multitaps on shift.
   */
  'T_*_MT_SHIFT_TO_SHIFT',
  'T_*_MT_SHIFT_TO_CAPS',
  'T_*_MT_SHIFT_TO_DEFAULT'
] as const;

/* A map of key field names with values matching the `typeof` the corresponding property
 * exists in /web/src/engine/keyboard/src/keyboards/activeLayout.ts.
 *
 * Make sure that when one is updated, the other also is.  TS types are compile-time only,
 * so the run-time-accessible mapping in activeLayout.ts cannot be auto-generated by TS. */
/** defines a key on a touch layout */
export interface TouchLayoutKey {
  /** key id: used to find key in VKDictionary, or a standard key from the K_ enumeration */
  id?: TouchLayoutKeyId;
  /** text to display on key cap */
  text?: string;
  /**
    * the modifier combination (not layer) that should be used in key events,
    * for this key, overriding the layer that the key is a part of.
    */
  layer?: TouchLayoutLayerId;
  /** the next layer to switch to after this key is pressed */
  nextlayer?: TouchLayoutLayerId;
  /** font */
  font?: TouchLayoutFont;
  /** fontsize */
  fontsize?: TouchLayoutFontSize;
  /** the type of key */
  sp?: TouchLayoutKeySp;
  /** padding */
  pad?: TouchLayoutKeyPad;
  /** width of the key */
  width?: TouchLayoutKeyWidth;
  /** longpress keys, also known as subkeys */
  sk?: TouchLayoutSubKey[];
  /** flicks */
  flick?: TouchLayoutFlick;
  /** multitaps */
  multitap?: TouchLayoutSubKey[];
  /** hint e.g. for longpress */
  hint?: string;
};

/** key type like regular key, framekeys, deadkeys, blank, etc. */
export const enum TouchLayoutKeySp {
  normal=0,
  /** A 'frame' key, such as Shift or Enter, which is styled accordingly; uses
   *  the 'KeymanwebOsk' font on KeymanWeb */
  special=1,
  /** A 'frame' key, such as Shift or Enter, which is styled accordingly and is
   *  highlighted to indicate it is active, such as the shift key on a shift
   *  layer; uses the 'KeymanwebOsk' font on KeymanWeb */
  specialActive=2,
  /** **KeymanWeb runtime private use:** a variant of `special` with the
   *  keyboard font rather than 'KeymanwebOsk' font */
  customSpecial=3,
  /** **KeymanWeb runtime private use:** a  variant of `specialActive` with the
   *  keyboard font rather than 'KeymanwebOsk' font. */
  customSpecialActive=4,
  /** A styling signal to indicate that the key may have 'deadkey' type
   *  behaviour. */
  deadkey=8,
  /** A key which is rendered as a blank keycap, blocks any interaction */
  blank=9,
  /** Renders the key only as a gap or spacer, blocks any interaction */
  spacer=10
};

/** padding for a key */
export type TouchLayoutKeyPad = number; // 0-100000
/** width of a key */
export type TouchLayoutKeyWidth = number; // 0-100000

/** defines a subkey */
export interface TouchLayoutSubKey {
  /** key id: used to find key in VKDictionary, or a standard key from the K_ enumeration */
  id: TouchLayoutKeyId;
  /** text to display on key cap */
  text?: string;
  /**
    * the modifier combination (not layer) that should be used in key events,
    * for this key, overriding the layer that the key is a part of.
    */
  layer?: TouchLayoutLayerId;
  /** the next layer to switch to after this key is pressed */
  nextlayer?: TouchLayoutLayerId;
  /** font */
  font?: TouchLayoutFont;
  /** fontsize */
  fontsize?: TouchLayoutFontSize;
  /** the type of key */
  sp?: TouchLayoutKeySp;
  /** padding */
  pad?: TouchLayoutKeyPad;
  /** width of the key */
  width?: TouchLayoutKeyWidth;
  /** use this subkey if no other selected */
  default?: boolean;  // Only used for longpress currently
};

/** defines all possible flicks for a key */
export interface TouchLayoutFlick {
  /** flick up (north) */
  n?: TouchLayoutSubKey;
  /** flick down (south) */
  s?: TouchLayoutSubKey;
  /** flick right (east) */
  e?: TouchLayoutSubKey;
  /** flick left (west) */
  w?: TouchLayoutSubKey;
  /** flick up-right (north-east) */
  ne?: TouchLayoutSubKey;
  /** flick up-left (north-west) */
  nw?: TouchLayoutSubKey;
  /** flick down-right (south-east) */
  se?: TouchLayoutSubKey;
  /** flick down-left (south-west) */
  sw?: TouchLayoutSubKey;
};
