import type { DatabaseInfo, FilterBehaviour, ForeignKeyInfo, NamedObjectInfo, TableInfo } from 'dbgate-types';
import uuidv1 from 'uuid/v1';

// export interface PerspectiveConfigColumns {
//   expandedColumns: string[];
//   checkedColumns: string[];
//   uncheckedColumns: string[];
// }

export type PerspectiveDatabaseEngineType = 'sqldb' | 'docdb';

export interface PerspectiveDatabaseConfig {
  conid: string;
  database: string;
}

export interface PerspectiveCustomJoinConfig {
  refNodeDesignerId: string;
  referenceDesignerId: string;
  joinName: string;
  baseDesignerId: string;
  conid?: string;
  database?: string;
  refSchemaName?: string;
  refTableName: string;
  columns: {
    baseColumnName: string;
    refColumnName: string;
  }[];
}

export interface PerspectiveFilterColumnInfo {
  columnName: string;
  filterBehaviour: FilterBehaviour;
  pureName: string;
  schemaName: string;
  foreignKey: ForeignKeyInfo;
}

// export interface PerspectiveParentFilterConfig {
//   uniqueName: string;
// }
// export interface PerspectiveConfig extends PerspectiveConfigColumns {
//   rootObject: { schemaName?: string; pureName: string };
//   filters: { [uniqueName: string]: string };
//   sort: {
//     [parentUniqueName: string]: {
//       uniqueName: string;
//       order: 'ASC' | 'DESC';
//     }[];
//   };
//   customJoins: PerspectiveCustomJoinConfig[];
//   parentFilters: PerspectiveParentFilterConfig[];
// }

export interface PerspectiveNodeConfig {
  designerId: string;
  schemaName?: string;
  pureName: string;
  defaultColumnsProcessed?: boolean;

  alias?: string;

  conid?: string;
  database?: string;

  isParentFilter?: boolean;

  expandedColumns: string[];
  checkedColumns: string[];
  columnDisplays: {};
  // uncheckedColumns: string[];

  sort: {
    columnName: string;
    order: 'ASC' | 'DESC';
  }[];

  filters: { [uniqueName: string]: string };
  isAutoGenerated?: true | undefined;
  isNodeChecked?: boolean;

  multiColumnFilter?: string;

  position?: {
    x: number;
    y: number;
  };
}

export interface PerspectiveReferenceConfig {
  designerId: string;

  sourceId: string;
  targetId: string;

  columns: {
    source: string;
    target: string;
  }[];

  isAutoGenerated?: true | undefined;
}

export interface PerspectiveConfig {
  rootDesignerId: string;
  isArranged: boolean;
  nodes: PerspectiveNodeConfig[];
  references: PerspectiveReferenceConfig[];
}

export function createPerspectiveNodeConfig(name: { schemaName?: string; pureName: string }) {
  const node: PerspectiveNodeConfig = {
    pureName: name.pureName,
    schemaName: name.schemaName,
    designerId: uuidv1(),

    expandedColumns: [],
    checkedColumns: [],
    columnDisplays: {},

    sort: [],
    filters: {},

    isNodeChecked: true,
  };

  return node;
}

export function createPerspectiveConfig(rootObject?: { schemaName?: string; pureName: string }): PerspectiveConfig {
  if (!rootObject) {
    return {
      nodes: [],
      references: [],
      isArranged: true,
      rootDesignerId: null,
    };
  }

  const rootNode = createPerspectiveNodeConfig(rootObject);
  return {
    nodes: [rootNode],
    references: [],
    rootDesignerId: rootNode.designerId,
    isArranged: true,
  };
}

export type ChangePerspectiveConfigFunc = (
  changeFunc: (config: PerspectiveConfig) => PerspectiveConfig,
  reload?: boolean
) => void;

export function extractPerspectiveDatabases(
  { conid, database },
  cfg: PerspectiveConfig
): { conid: string; database: string }[] {
  const res: { conid: string; database: string }[] = [];
  res.push({ conid, database });

  function add(conid, database) {
    if (res.find(x => x.conid == conid && x.database == database)) return;
    res.push({ conid, database });
  }

  for (const node of cfg.nodes) {
    add(node.conid || conid, node.database || database);
  }
  return res;
}

export interface MultipleDatabaseInfo {
  [conid: string]: {
    [database: string]: DatabaseInfo;
  };
}

export function switchPerspectiveReferenceDirection(ref: PerspectiveReferenceConfig): PerspectiveReferenceConfig {
  return {
    designerId: ref.designerId,
    sourceId: ref.targetId,
    targetId: ref.sourceId,
    isAutoGenerated: ref.isAutoGenerated,
    columns: ref.columns.map(x => ({ source: x.target, target: x.source })),
  };
}
