import * as Models from '../models/models';
import MongooseDeletes from './mongoose-deletes';
import MongooseInserts from './mongoose-inserts';
import MongooseQueries from './mongoose-queries';
import MoongosseConnection from './mongoose-connection';
import mongoose = require( 'mongoose' );

export class MongooseHelper {
  private userProperties: Models.UserProperties;

  public constructor( userProperties: Models.UserProperties ) {
    this.userProperties = userProperties;

    // mongoose.plugin( ( schema: mongoose.Schema ) => {
    //   schema.options.toJSON = {
    //     virtuals: true,
    //     versionKey: false,
    //     transform( doc, ret ) {
    //       ret.id = ret._id;
    //       delete ret._id;
    //     }
    //   };
    // } );
  }

  public async insertReport( report: Models.ExtendedReport ): Promise<mongoose.Types.ObjectId> {
    const connection = await new MoongosseConnection( this.userProperties ).connect();
    const models = this.initalizeModels( connection );
    const objectId = await new MongooseInserts( models ).insertReport( report );
    await connection.close();
    return objectId;
  }

  public async getReportById( id: mongoose.Types.ObjectId | string ): Promise<Models.ExtendedReport> {
    const connection = await new MoongosseConnection( this.userProperties ).connect();
    const models = this.initalizeModels( connection );
    const report = await new MongooseQueries( models ).getReportById( id );
    await connection.close();
    return report;
  }

  public async getAllTheElementsOrderedAndFiltered( orderValue: string, orderDirection: number, filterValue: string ): Promise<Models.ExtendedReport[]> {
    const connection = await new MoongosseConnection( this.userProperties ).connect();
    const models = this.initalizeModels( connection );
    const reports = await new MongooseQueries( models ).getAllTheElementsOrderedAndFiltered( orderValue, orderDirection, filterValue );
    await connection.close();
    return reports;
  }

  public async deleteReportById( id: mongoose.Types.ObjectId | string ): Promise<void> {
    const connection = await new MoongosseConnection( this.userProperties ).connect();
    const models = this.initalizeModels( connection );
    await new MongooseDeletes( models ).deleteReportById( id );
    await connection.close();
  }

  public async getDatabaseSize( ): Promise<number>{
    const mongooseConnection = new MoongosseConnection( this.userProperties );
    const connection = await mongooseConnection.connect();
    const databaseSize = await mongooseConnection.getDatabaseSize( );
    await connection.close();
    return databaseSize;
  }

  private initalizeModels( mongooseConnection: mongoose.Connection ): Models.MongooseModels {
    return {
      featureModel: mongooseConnection.model<Models.MFeature>(
        'Feature',
        Models.featureSchema,
        this.userProperties.mongoDb?.collections.features,
      ),
      reportModel: mongooseConnection.model<Models.MExtendedReport>(
        'ExtendedReport',
        Models.reportsSchema,
        this.userProperties.mongoDb?.collections.reports,
      ),
      scenarioModel: mongooseConnection.model<Models.MScenario>(
        'Scenario',
        Models.scenarioSchema,
        this.userProperties.mongoDb?.collections.scenarios,
      ),
      stepModel: mongooseConnection.model<Models.MSTep>(
        'Step',
        Models.stepSchema,
        this.userProperties.mongoDb?.collections.steps,
      ),
    };
  }
}
