import { NextFunction, Request, Response } from "express";
import { autowired } from "first-di";
import { EntityRepository } from "../../core/repository/entity_repository";
import { port } from "../../server";
import { memoAsync } from "../../core/helper/memorization";
  
export class AssemblyPreviewsController {
  @autowired()
  private readonly entityRepository: EntityRepository;

  public getAllAssembly = async (
    req: Request,
    res: Response,
    next: NextFunction
  ): Promise<void> => {
    try {
      res.send(await this.entityRepository.getAllRootEntity());
    } catch (error) {
      next(error);
    }
  };

  public getAssemblySubsequenceById = async (
    req: Request,
    res: Response,
    next: NextFunction
  ): Promise<void> => {
    try {
      const entity = await this.entityRepository.getEntityStorage(
        req.params.id
      );

      const aspUsage = Number(req.query.count) - 1;
      
      if (entity === undefined) {
        res.status(404).json("entity not found");
        return;
      }

      res.json(
        await this._assemblyCompute(
          aspUsage,
          entity,
          this.entityRepository,
          req.hostname,
          req.params.id
        )
      );
    } catch (error) {
      next(error);
    }
  };

  public getAssemblyInsertionSequenceById = async (
    req: Request,
    res: Response,
    next: NextFunction
  ) => {
    const entity = await this.entityRepository.getEntityStorage(req.params.id);

    const aspUsage = Number(req.query.count);
    
    const assemblyFolder = entity.find((el) => {
      return el.match("assembly");
    });
    
    const asmCountFolder = "0000" + aspUsage;

    const assemblyDirPath = assemblyFolder + "/" + asmCountFolder;

    if (!this.entityRepository.isExistDirPath(assemblyDirPath)) {
      return res.status(400).json({ error: "bad request" });
    }
    
    const assemblyProcessDir = await this.entityRepository.getDir(
      assemblyDirPath + "/process/"
    );
    
    const firstObj = assemblyProcessDir.find((el) => {
      return el.match("1.obj");
    });

    const zeroObj = await assemblyProcessDir.find((el) => {
      return el.match("0.obj");
    });

    const insertions = await this.entityRepository.readJson(
      assemblyDirPath + "/" + "insertion_path.json"
    );

    if (
      insertions === undefined ||
      zeroObj === undefined ||
      firstObj === undefined
    ) {
      res.status(400).json({ error: "bad" });
      return;
    }

    res.json({
      offset: aspUsage,
      count: 4,
      parent: `http://${req.hostname}:${port}/${
        req.params.id
      }/assembly/${asmCountFolder}/${0}.obj`,

      child: `http://${req.hostname}:${port}/${
        req.params.id
      }/assembly/${asmCountFolder}/${1}.obj`,

      insertions: insertions,
    });
    return;
  };
  private async _assemblyCompute(
    id: number,
    entityFolder: Array<String>,
    repository: EntityRepository,
    host: string,
    entity: string
  ) {
    const assemblySequence = entityFolder.find((el) => {
      return el.match("step-structure.json");
    });

    const assembly: Array<String> = await repository.readJson<Array<String>>(
      assemblySequence
    );

    if (id == 0) {
      return {
        assembly: [
          `http://${host}:${port}/${entity}/sdf/meshes/${assembly[id]}.obj`,
        ],
        offset: 1,
        count: assemblySequence.length,
      };
    } else {
      const assemblyIndexed = assembly
        .map((_item, index) => {
          if (index <= id) {
            return index;
          }
        })
        .filter((el) => el != undefined);
      return {
        assembly: assemblyIndexed.map((el) => {
          return `http://${host}:${port}/${entity}/sdf/meshes/${assembly[el]}.obj`;
        }),
        count: assemblyIndexed.length,
        offset: assembly.length,
      };
    }
  }
  
}
