import v4 from '../../lib/uuid.js'
import { File, IFile } from './File.js'
import { Thing } from '../Thing.js'
import { DataNamespace, IDataNamespace } from '../../modeling/DataNamespace.js'
import { DataFileKind as Kind } from '../kinds.js'

export interface IDataFile extends IFile {
  kind: typeof Kind
}

/**
 * Used by the store. A file definition for the DataNamespace
 */
export class DataFile extends File {
  override kind = Kind

  /**
   * Creates the file definition for a DataNamespace contents.
   *
   * @param input The data namespace instance or schema.
   * @param owner Optional owner to set.
   */
  static fromDataNamespace(input: DataNamespace | IDataNamespace, organization: string, owner?: string): DataFile {
    let final: IDataNamespace
    if (typeof (input as DataNamespace).toJSON === 'function') {
      final = (input as DataNamespace).toJSON()
    } else {
      final = input as IDataNamespace
    }
    const init: IDataFile = {
      kind: Kind,
      key: final.key,
      organization,
      info: { ...final.info },
      lastModified: { user: owner || '', time: 0, byMe: false },
      owner,
      parents: [],
      permissionIds: [],
      permissions: [],
    }
    return new DataFile(init)
  }

  /**
   * @param name The name to set.
   * @param owner The user id that is the owner of the file.
   */
  static override fromName(name: string, organization: string, owner?: string): DataFile {
    return super.fromName(name, organization, owner, Kind) as DataFile
  }

  constructor(input?: string | IDataFile) {
    super()
    let init: IDataFile
    if (typeof input === 'string') {
      init = JSON.parse(input)
    } else if (typeof input === 'object') {
      init = input
    } else {
      init = {
        kind: Kind,
        key: v4(),
        organization: '',
        info: Thing.fromName('').toJSON(),
        parents: [],
        permissionIds: [],
        permissions: [],
        lastModified: { user: '', time: 0, byMe: false },
      }
    }
    this.new(init)
  }

  override new(init: IDataFile): this {
    if (!DataFile.isDataFile(init)) {
      throw new Error(`Not a data file.`)
    }
    super.new(init)
    this.kind = Kind
    return this
  }

  static isDataFile(input: unknown): boolean {
    const typed = input as IDataFile
    if (!input || typed.kind !== Kind) {
      return false
    }
    return true
  }

  override toJSON(): IDataFile {
    const result: IDataFile = {
      ...super.toJSON(),
      kind: Kind,
    }
    return result
  }
}
