import { Connection } from 'typeorm';
import { AssetBlockCompEntity } from '../../entities/asset-block-comp.entity';
import { AssetBlockEntity } from '../../entities/asset-block.entity';
import { EventTriggerEntity } from '../../entities/event-trigger.entity';
import { AssetProps } from './Props';

export class ComputingContext {
  cachedComputedBlocks: {
    [assetId: string]: {
      [blockKey: string]: AssetBlockCompEntity;
    };
  } = {};
  cachedOriginalBlocks: {
    [assetId: string]: {
      [blockKey: string]: AssetBlockEntity;
    };
  } = {};
  changedComputedBlocks: {
    [assetId: string]: {
      [blockKey: string]: {
        old: AssetProps;
        new: AssetProps;
      };
    };
  } = {};
  eventTriggers: EventTriggerEntity[];
  constructor(public projectId: string, public operations: number) {}

  async init(database: Connection) {
    this.eventTriggers = await database.getRepository(EventTriggerEntity).find({
      projectId: this.projectId,
    });
  }

  addChangedBlockKeyOfAsset(
    asset_id: string,
    block_key: string,
    old_computed_props: AssetProps,
    new_computed_props: AssetProps,
  ) {
    if (!this.changedComputedBlocks.hasOwnProperty(asset_id)) {
      this.changedComputedBlocks[asset_id] = {};
    }
    if (!this.changedComputedBlocks[asset_id].hasOwnProperty(block_key)) {
      this.changedComputedBlocks[asset_id][block_key] = {
        old: old_computed_props,
        new: new_computed_props,
      };
    } else {
      this.changedComputedBlocks[asset_id][block_key].new = new_computed_props;
    }
  }

  addComputedListToCache(blocks: AssetBlockCompEntity[]) {
    for (const block of blocks) {
      let assetBlocks;
      if (this.cachedComputedBlocks.hasOwnProperty(block.assetId)) {
        assetBlocks = this.cachedComputedBlocks[block.assetId];
      } else {
        assetBlocks = {};
        this.cachedComputedBlocks[block.assetId] = assetBlocks;
      }
      assetBlocks[block.blockKey] = block;
    }
  }

  addOriginalListToCache(blocks: AssetBlockEntity[]) {
    for (const block of blocks) {
      let assetBlocks;
      if (this.cachedOriginalBlocks.hasOwnProperty(block.assetId)) {
        assetBlocks = this.cachedOriginalBlocks[block.assetId];
      } else {
        assetBlocks = {};
        this.cachedOriginalBlocks[block.assetId] = assetBlocks;
      }
      assetBlocks[block.blockKey] = block;
    }
  }

  getComputedBlockFromCache(
    asset_id: string,
    block_key: string,
  ): AssetBlockCompEntity | undefined {
    if (!this.cachedComputedBlocks.hasOwnProperty(asset_id)) return undefined;
    const assetBlocks = this.cachedComputedBlocks[asset_id];
    if (!assetBlocks.hasOwnProperty(block_key)) return undefined;
    return assetBlocks[block_key];
  }

  getOriginalBlockFromCache(
    asset_id: string,
    block_key: string,
  ): AssetBlockEntity | undefined {
    if (!this.cachedOriginalBlocks.hasOwnProperty(asset_id)) return undefined;
    const assetBlocks = this.cachedOriginalBlocks[asset_id];
    if (!assetBlocks.hasOwnProperty(block_key)) return undefined;
    return assetBlocks[block_key];
  }
}
