'use strict';

import * as fs from 'fs';
import * as path from 'path';
import * as fse from 'fs-extra';
const fsp = fs.promises;
import { Feature, ExtendedReport } from 'json-html-reporter-models';
import * as jsonFuture from 'json-future';

export class FileSystemFunctions {
  public getFilesAsync = async ( dir: string ): Promise<string[]> => {
    let files: string[] = [];
    const getFiles = async ( folder: string ): Promise<string[]> => {
      files = await fsp.readdir( folder );
      const result = files.map( file => {
        const p = path.join( folder, file );
        return fsp.stat( p ).then( stat => ( stat.isDirectory() ? getFiles( p ) : [p] ) );
      } );
      return Array.prototype.concat( ...( await Promise.all( result ) ) ); // Flatten
    };

    return getFiles( dir );
  };

  public checkFolder = async ( file: string ): Promise<boolean> => fsp
    .stat( file )
    .then( result => result.isDirectory() )
    .catch( () => false );

  public readJsonFeatureFile = async ( file: string, encoding: string = "utf8" ): Promise<Feature[]> => fse.readJson( file, <fse.ReadOptions>{ encoding } )
    .catch( error => {
      console.log( `The file ${file} is not a valid json, it has the error message ${error.message}` );
      return null;
  } );

  public readJsonExtendedReportFile = async ( file: string, encoding: string = "utf8" ): Promise<ExtendedReport> => fse.readJson( file, <fse.ReadOptions>{ encoding } )
    .catch( error => {
      console.log( `The file ${file} is not a valid json, it has the error message ${error.message}` );
      return null;
  } );

  public parseJsonObject = async (jsonObject: string) => {
    return jsonFuture.parseAsync(await jsonFuture.stringifyAsync(jsonObject));
};

  public readFeatureFile = async ( file: string, enconding: string ): null | Promise<Feature[]> => {
    const parsedReport = await this.readJsonFeatureFile( file, enconding );

    if (
      parsedReport == null ||
      typeof parsedReport.length === 'undefined' ||
      parsedReport.length === 0 ||
      typeof parsedReport[0].id === 'undefined' ||
      typeof parsedReport[0].keyword === 'undefined'
    ) {
      const arr: Feature[] = [];
      return arr;
    }

    return parsedReport;
  };

  public writeJson = async (destinationFile: string, jsonObject: any): Promise<void> => {
    return await fse.writeFile(destinationFile, jsonObject);
  };

  public convertJsonObjectToString = async (object: Object): Promise<string> =>{
    return await jsonFuture.stringifyAsync(Object);
  }
}