type JsonRecord = Record<string, unknown>;

function isRecord(value: unknown): value is JsonRecord {
  return typeof value === "object" && value !== null && !Array.isArray(value);
}

function readString(data: JsonRecord, key: string, fallback = "") {
  const value = data[key];
  return value === null || value === undefined ? fallback : String(value);
}

function readNumber(data: JsonRecord, key: string, fallback = 0) {
  const value = data[key];
  if (typeof value === "number") return Number.isFinite(value) ? value : fallback;
  if (typeof value === "string" && value.trim() !== "") {
    const parsed = Number(value);
    return Number.isFinite(parsed) ? parsed : fallback;
  }
  return fallback;
}

function readBoolean(data: JsonRecord, key: string, fallback = false) {
  const value = data[key];
  if (typeof value === "boolean") return value;
  if (typeof value === "number") return value !== 0;
  if (typeof value === "string") {
    if (value.toLowerCase() === "true") return true;
    if (value.toLowerCase() === "false") return false;
  }
  return fallback;
}

function readArray(data: JsonRecord, key: string) {
  const value = data[key];
  return Array.isArray(value) ? value : [];
}

class P_OPERATION {
  /**
   * 一组项目帧
   */
  OPERATION = new C_OPERATION();

  constructor(operation?: C_OPERATION) {
    if (operation) {
      this.OPERATION = operation;
    }
  }

  /**
   * 从JSON数据反序列化
   * @param jsonData JSON格式的数据
   * @returns P_OPERATION
   */
  static fromjson(jsonData: unknown) {
    const operation = new P_OPERATION();
    if (isRecord(jsonData) && isRecord(jsonData.OPERATION)) {
      operation.OPERATION = C_OPERATION.fromjson(jsonData.OPERATION);
    }
    return operation;
  }
}

class C_OPERATION {
  /**
   * 帧集合
   */
  frames: C_Frames[] = [];

  constructor(frames?: C_Frames[]) {
    this.frames = frames || [];
  }

  /**
   * 从JSON数据反序列化
   * @param jsonData JSON格式的数据
   * @returns C_OPERATION
   */
  static fromjson(jsonData: unknown) {
    const operation = new C_OPERATION();
    if (isRecord(jsonData)) {
      operation.frames = readArray(jsonData, "frames").map((frameData) => C_Frames.fromjson(frameData));
    }
    return operation;
  }
}

class C_Frames {
  /**
   * 帧时间
   */
  time = "0.01";
  /**
   * 帧内容集合
   */
  objStates: C_ObjStates[] = [];
  crafts: C_Craft[] = [];
  signalwrites: C_Signalwrite[] = [];
  visibles: C_Visible[] = [];
  rotations: C_Rotation[] = [];
  waits: C_Wait[] = [];
  attachs: C_Attach[] = [];

  constructor(frame?: Partial<C_Frames>) {
    if (frame) {
      this.time = frame.time ?? this.time;
      this.objStates = frame.objStates ?? this.objStates;
      this.crafts = frame.crafts ?? this.crafts;
      this.signalwrites = frame.signalwrites ?? this.signalwrites;
      this.visibles = frame.visibles ?? this.visibles;
      this.rotations = frame.rotations ?? this.rotations;
      this.waits = frame.waits ?? this.waits;
      this.attachs = frame.attachs ?? this.attachs;
    }
  }

  /**
   * 从JSON数据反序列化
   * @param jsonData JSON格式的数据
   * @returns C_Frames实例
   */
  static fromjson(jsonData: unknown) {
    const frame = new C_Frames();
    if (isRecord(jsonData)) {
      frame.time = readString(jsonData, "time", frame.time);
      frame.objStates = readArray(jsonData, "objStates").map((objStateData) => C_ObjStates.fromjson(objStateData));
      frame.crafts = readArray(jsonData, "crafts").map((craftData) => C_Craft.fromjson(craftData));
      frame.signalwrites = readArray(jsonData, "signalwrites").map((signalData) => C_Signalwrite.fromjson(signalData));
      frame.visibles = readArray(jsonData, "visibles").map((visibleData) => C_Visible.fromjson(visibleData));
      frame.rotations = readArray(jsonData, "rotations").map((rotationData) => C_Rotation.fromjson(rotationData));
      frame.waits = readArray(jsonData, "waits").map((waitData) => C_Wait.fromjson(waitData));
      frame.attachs = readArray(jsonData, "attachs").map((attachData) => C_Attach.fromjson(attachData));
    }
    return frame;
  }
}

class C_ObjStates {
  /**
   * 模型代码
   */
  i = "";
  /**
   * tx
   */
  tx = "";
  /**
   * ty
   */
  ty = "";
  /**
   * tz
   */
  tz = "";
  /**
   * qx
   */
  qx = "";
  /**
   * qy
   */
  qy = "";
  /**
   * qz
   */
  qz = "";
  /**
   * qw
   */
  qw = "";

  constructor(objState?: Partial<C_ObjStates>) {
    if (objState) {
      this.i = objState.i ?? this.i;
      this.tx = objState.tx ?? this.tx;
      this.ty = objState.ty ?? this.ty;
      this.tz = objState.tz ?? this.tz;
      this.qx = objState.qx ?? this.qx;
      this.qy = objState.qy ?? this.qy;
      this.qz = objState.qz ?? this.qz;
      this.qw = objState.qw ?? this.qw;
    }
  }

  /**
   * 从JSON数据反序列化
   * @param jsonData JSON格式的数据
   * @returns C_ObjStates实例
   */
  static fromjson(jsonData: unknown) {
    const objState = new C_ObjStates();
    if (isRecord(jsonData)) {
      objState.i = readString(jsonData, "i", objState.i);
      objState.tx = readString(jsonData, "tx", objState.tx);
      objState.ty = readString(jsonData, "ty", objState.ty);
      objState.tz = readString(jsonData, "tz", objState.tz);
      objState.qx = readString(jsonData, "qx", objState.qx);
      objState.qy = readString(jsonData, "qy", objState.qy);
      objState.qz = readString(jsonData, "qz", objState.qz);
      objState.qw = readString(jsonData, "qw", objState.qw);
    }
    return objState;
  }
}

class C_Craft {
  CraftCode = "";
  CraftValue = "";

  constructor(craft?: Partial<C_Craft>) {
    if (craft) {
      this.CraftCode = craft.CraftCode ?? this.CraftCode;
      this.CraftValue = craft.CraftValue ?? this.CraftValue;
    }
  }

  /**
   * 从JSON数据反序列化
   * @param jsonData JSON格式的数据
   * @returns C_Craft实例
   */
  static fromjson(jsonData: unknown) {
    const craft = new C_Craft();
    if (isRecord(jsonData)) {
      craft.CraftCode = readString(jsonData, "CraftCode", craft.CraftCode);
      craft.CraftValue = readString(jsonData, "CraftValue", craft.CraftValue);
    }
    return craft;
  }
}

class C_Signalwrite {
  /**
   * TagID
   */
  TagID = "";
  /**
   * TagValue
   */
  TagValue = "";

  constructor(signal?: Partial<C_Signalwrite>) {
    if (signal) {
      this.TagID = signal.TagID ?? this.TagID;
      this.TagValue = signal.TagValue ?? this.TagValue;
    }
  }

  /**
   * 从JSON数据反序列化
   * @param jsonData JSON格式的数据
   * @returns C_Signalwrite实例
   */
  static fromjson(jsonData: unknown) {
    const signal = new C_Signalwrite();
    if (isRecord(jsonData)) {
      signal.TagID = readString(jsonData, "TagID", signal.TagID);
      signal.TagValue = readString(jsonData, "TagValue", signal.TagValue);
    }
    return signal;
  }
}

class C_Visible {
  ModelCode = "";
  Visible = "";

  constructor(visible?: Partial<C_Visible>) {
    if (visible) {
      this.ModelCode = visible.ModelCode ?? this.ModelCode;
      this.Visible = visible.Visible ?? this.Visible;
    }
  }

  /**
   * 从JSON数据反序列化
   * @param jsonData JSON格式的数据
   * @returns C_Visible
   */
  static fromjson(jsonData: unknown) {
    const visible = new C_Visible();
    if (isRecord(jsonData)) {
      visible.ModelCode = readString(jsonData, "ModelCode", visible.ModelCode);
      visible.Visible = readString(jsonData, "Visible", visible.Visible);
    }
    return visible;
  }
}

class C_Rotation {
  ModelCode = "";
  Axis = "";
  Rate = 0;

  constructor(rotation?: Partial<C_Rotation>) {
    if (rotation) {
      this.ModelCode = rotation.ModelCode ?? this.ModelCode;
      this.Axis = rotation.Axis ?? this.Axis;
      this.Rate = rotation.Rate ?? this.Rate;
    }
  }

  /**
   * 从JSON数据反序列化
   * @param jsonData JSON格式的数据
   * @returns C_Rotation
   */
  static fromjson(jsonData: unknown) {
    const rotation = new C_Rotation();
    if (isRecord(jsonData)) {
      rotation.ModelCode = readString(jsonData, "ModelCode", rotation.ModelCode);
      rotation.Axis = readString(jsonData, "Axis", rotation.Axis);
      rotation.Rate = readNumber(jsonData, "Rate", rotation.Rate);
    }
    return rotation;
  }
}

class C_Wait {
  WaitStr = "";

  constructor(wait?: Partial<C_Wait>) {
    if (wait) {
      this.WaitStr = wait.WaitStr ?? this.WaitStr;
    }
  }

  /**
   * 从JSON数据反序列化
   * @param jsonData JSON格式的数据
   * @returns C_Wait实例
   */
  static fromjson(jsonData: unknown) {
    const wait = new C_Wait();
    if (isRecord(jsonData)) {
      wait.WaitStr = readString(jsonData, "WaitStr", wait.WaitStr);
    }
    return wait;
  }
}

class C_Attach {
  AttachToModelCode = "";
  AttachToModelName = "";
  List_AttachModel: ModelGroup[] = [];
  IsTwoWay = false;
  IsAttach = false;

  constructor(attach?: Partial<C_Attach>) {
    if (attach) {
      this.AttachToModelCode = attach.AttachToModelCode ?? this.AttachToModelCode;
      this.AttachToModelName = attach.AttachToModelName ?? this.AttachToModelName;
      this.List_AttachModel = attach.List_AttachModel ?? this.List_AttachModel;
      this.IsTwoWay = attach.IsTwoWay ?? this.IsTwoWay;
      this.IsAttach = attach.IsAttach ?? this.IsAttach;
    }
  }

  /**
   * 从JSON数据反序列化
   * @param jsonData JSON格式的数据
   * @returns C_Attach实例
   */
  static fromjson(jsonData: unknown) {
    const attach = new C_Attach();
    if (isRecord(jsonData)) {
      attach.AttachToModelCode = readString(jsonData, "AttachToModelCode", attach.AttachToModelCode);
      attach.AttachToModelName = readString(jsonData, "AttachToModelName", attach.AttachToModelName);
      attach.IsTwoWay = readBoolean(jsonData, "IsTwoWay", attach.IsTwoWay);
      attach.IsAttach = readBoolean(jsonData, "IsAttach", attach.IsAttach);
      attach.List_AttachModel = readArray(jsonData, "List_AttachModel")
        .filter(isRecord)
        .map((modelData) => new ModelGroup(
          readString(modelData, "ModelCode"),
          readString(modelData, "ModelName")
        ));
    }
    return attach;
  }
}

// / <summary>
// / 焦点选择描述
// / 2025.08.17.2050.LLX
// / </summary>
class C_Focus {
  id = "";
  name = "";
  time = "3000";

  constructor(focus?: Partial<C_Focus>) {
    if (focus) {
      this.id = focus.id ?? this.id;
      this.name = focus.name ?? this.name;
      this.time = focus.time ?? this.time;
    }
  }

  /**
   * 从JSON数据反序列化
   * @param jsonData JSON格式的数据
   * @returns C_Focus
   */
  static fromjson(jsonData: unknown) {
    const focus = new C_Focus();
    if (isRecord(jsonData)) {
      focus.id = readString(jsonData, "id", focus.id);
      focus.name = readString(jsonData, "name", focus.name);
      focus.time = readString(jsonData, "time", focus.time);
    }
    return focus;
  }
}

class ModelGroup {
  /**
   * 模型代码
   */
  ModelCode = "";
  /**
   * 模型名称
   */
  ModelName = "";

  /**
   * 构造函数
   * @param modelCode 模型代码
   * @param modelName 模型名称
   */
  constructor(modelCode = "", modelName = "") {
    this.ModelCode = modelCode;
    this.ModelName = modelName;
  }
}

export {
  C_Attach,
  C_Craft,
  C_Frames,
  C_OPERATION,
  C_ObjStates,
  C_Rotation,
  C_Signalwrite,
  C_Visible,
  C_Wait,
  ModelGroup,
  P_OPERATION,
  C_Focus
};
