//test orphaning the generator before FT
TEST_F(EnergyPlusFixture, ForwardTranslatorGeneratorMicroTurbine_ELCD_Orphan)
{
  // Create a model, a mchp, a mchpHR, a plantLoop and an electricalLoadCenter
  Model model;

  GeneratorMicroTurbine mchp = GeneratorMicroTurbine(model);
  GeneratorMicroTurbineHeatRecovery mchpHR = GeneratorMicroTurbineHeatRecovery(model, mchp);
  ASSERT_EQ(mchpHR, mchp.generatorMicroTurbineHeatRecovery().get());

  PlantLoop plantLoop(model);
  // Add a supply branch for the mchpHR
  ASSERT_TRUE(plantLoop.addSupplyBranchForComponent(mchpHR));

  // Create a WaterHeater:Mixed
  WaterHeaterMixed waterHeater(model);
  // Add it on the same branch as the chpHR, right after it
  Node mchpHROutletNode = mchpHR.outletModelObject()->cast<Node>();
  ASSERT_TRUE(waterHeater.addToNode(mchpHROutletNode));

  // Create a plantEquipmentOperationHeatingLoad
  PlantEquipmentOperationHeatingLoad operation(model);
  operation.setName(plantLoop.name().get() + " PlantEquipmentOperationHeatingLoad");
  ASSERT_TRUE(plantLoop.setPlantEquipmentOperationHeatingLoad(operation));
  ASSERT_TRUE(operation.addEquipment(mchpHR));
  ASSERT_TRUE(operation.addEquipment(waterHeater));

  // Create an ELCD
  ElectricLoadCenterDistribution elcd = ElectricLoadCenterDistribution(model);
  elcd.setName("Capstone C65 ELCD");
  elcd.setElectricalBussType("AlternatingCurrent");
  elcd.addGenerator(mchp);

  // orphan the generator from the ELCD
  boost::optional<ElectricLoadCenterDistribution> elcd2 = mchp.electricLoadCenterDistribution();
  elcd2.get().remove();
  EXPECT_FALSE(mchp.electricLoadCenterDistribution());

  // Forward Translates
  ForwardTranslator forwardTranslator;
  Workspace workspace = forwardTranslator.translateModel(model);

  EXPECT_EQ(0u, forwardTranslator.errors().size());
  //ASSERT_EQ(1u, workspace.getObjectsByType(IddObjectType::WaterHeater_Mixed).size());
  ASSERT_EQ(0u, workspace.getObjectsByType(IddObjectType::ElectricLoadCenter_Distribution).size());

  //model.save(toPath("./ForwardTranslatorGeneratorMicroTurbine_ELCD_orhpan.osm"), true);
  //workspace.save(toPath("./ForwardTranslatorGeneratorMicroTurbine_ELCD_orphan.idf"), true);

}
boost::optional<IdfObject> ForwardTranslator::translateGeneratorMicroTurbine(model::GeneratorMicroTurbine & modelObject)
{
  IdfObject idfObject = createRegisterAndNameIdfObject(openstudio::IddObjectType::Generator_MicroTurbine, modelObject);


  //get the GeneratorMicroTurbineHeatRecovery as an optional straight component, if exists cast it to optional GeneratorMicroTurbineHeatRecovery
  // if cast is successful, get the object of class GeneratorMicroTurbineHeatRecovery
  boost::optional<GeneratorMicroTurbineHeatRecovery> generatorOptionalMicroTurbineHeatRecovery = modelObject.generatorMicroTurbineHeatRecovery();
  // If there is a Heat Recovery Object
  if (generatorOptionalMicroTurbineHeatRecovery) {
    // Get it
    GeneratorMicroTurbineHeatRecovery generatorMCHPHX = *generatorOptionalMicroTurbineHeatRecovery;
    
    // HeatRecoveryWaterInletNodeName
    // Inlet Node Name 
    if ( auto temp = generatorMCHPHX.inletModelObject() )
    {
      auto s = temp->name();
      if(s)
      {
        idfObject.setString(openstudio::Generator_MicroTurbineFields::HeatRecoveryWaterInletNodeName,*s);
      }
    }

    //HeatRecoveryWaterOutletNodeName
    if ( auto temp = generatorMCHPHX.outletModelObject() ) {
      auto s = temp->name();
      if (s) {
        idfObject.setString(openstudio::Generator_MicroTurbineFields::HeatRecoveryWaterOutletNodeName, *s);
      }
    }

    //ReferenceThermalEfficiencyUsingLowerHeatValue
    {
      auto value = generatorMCHPHX.referenceThermalEfficiencyUsingLowerHeatValue();
      idfObject.setDouble(Generator_MicroTurbineFields::ReferenceThermalEfficiencyUsingLowerHeatValue, value);
    }

    //ReferenceInletWaterTemperature (double)
    idfObject.setDouble(Generator_MicroTurbineFields::ReferenceInletWaterTemperature, generatorMCHPHX.referenceInletWaterTemperature());

    
    //HeatRecoveryWaterFlowOperatingMode
    {
      auto value = generatorMCHPHX.heatRecoveryWaterFlowOperatingMode();
      idfObject.setString(Generator_MicroTurbineFields::HeatRecoveryWaterFlowOperatingMode,value);
    }

    //ReferenceHeatRecoveryWaterFlowRate (double)
    idfObject.setDouble(Generator_MicroTurbineFields::ReferenceHeatRecoveryWaterFlowRate, generatorMCHPHX.referenceHeatRecoveryWaterFlowRate());


    //HeatRecoveryWaterFlowRateFunctionofTemperatureandPowerCurve
    if( auto curve = generatorMCHPHX.heatRecoveryWaterFlowRateFunctionofTemperatureandPowerCurve() )  {
      if( auto _curve = translateAndMapModelObject(curve.get()) ) {
        idfObject.setString(Generator_MicroTurbineFields::HeatRecoveryWaterFlowRateFunctionofTemperatureandPowerCurveName,_curve->name().get());
      }
    }

    //ThermalEfficiencyFunctionofTemperatureandElevationCurve
    if( auto curve = generatorMCHPHX.thermalEfficiencyFunctionofTemperatureandElevationCurve() )  {
      if( auto _curve = translateAndMapModelObject(curve.get()) ) {
        idfObject.setString(Generator_MicroTurbineFields::ThermalEfficiencyFunctionofTemperatureandElevationCurveName,_curve->name().get());
      }
    }

    //HeatRecoveryRateFunctionofPartLoadRatioCurve
    if( auto curve = generatorMCHPHX.heatRecoveryRateFunctionofPartLoadRatioCurve() )  {
      if( auto _curve = translateAndMapModelObject(curve.get()) ) {
        idfObject.setString(Generator_MicroTurbineFields::HeatRecoveryRateFunctionofPartLoadRatioCurveName,_curve->name().get());
      }
    }

    //HeatRecoveryRateFunctionofInletWaterTemperatureCurve
    if( auto curve = generatorMCHPHX.heatRecoveryRateFunctionofInletWaterTemperatureCurve() )  {
      if( auto _curve = translateAndMapModelObject(curve.get()) ) {
        idfObject.setString(Generator_MicroTurbineFields::HeatRecoveryRateFunctionofInletWaterTemperatureCurveName,_curve->name().get());
      }
    }

    //HeatRecoveryRateFunctionofWaterFlowRateCurve
    if( auto curve = generatorMCHPHX.heatRecoveryRateFunctionofWaterFlowRateCurve() )  {
      if( auto _curve = translateAndMapModelObject(curve.get()) ) {
        idfObject.setString(Generator_MicroTurbineFields::HeatRecoveryRateFunctionofWaterFlowRateCurveName,_curve->name().get());
      }
    }

    //MinimumHeatRecoveryWaterFlowRate
    {
      auto value = generatorMCHPHX.minimumHeatRecoveryWaterFlowRate();
      idfObject.setDouble(Generator_MicroTurbineFields::MinimumHeatRecoveryWaterFlowRate,value);
    }

    //MaximumHeatRecoveryWaterFlowRate
    {
      auto value = generatorMCHPHX.maximumHeatRecoveryWaterFlowRate();
      idfObject.setDouble(Generator_MicroTurbineFields::MaximumHeatRecoveryWaterFlowRate,value);
    }

    //MaximumHeatRecoveryWaterTemperature
    if( auto value = generatorMCHPHX.maximumHeatRecoveryWaterTemperature() )
    {
      idfObject.setDouble(Generator_MicroTurbineFields::MaximumHeatRecoveryWaterTemperature,value.get());
    }
  }
  
  
  /// Doubles, non optional
  //ReferenceElectricalPowerOutput
  idfObject.setDouble(Generator_MicroTurbineFields::ReferenceElectricalPowerOutput, modelObject.referenceElectricalPowerOutput());

  //ReferenceElectricalEfficiencyUsingLowerHeatingValue
  idfObject.setDouble(Generator_MicroTurbineFields::ReferenceElectricalEfficiencyUsingLowerHeatingValue, modelObject.referenceElectricalEfficiencyUsingLowerHeatingValue());

  
  /// Doubles, optional
  //MinimumFullLoadElectricalPowerOutput
  {
    auto value = modelObject.minimumFullLoadElectricalPowerOutput();
    idfObject.setDouble(Generator_MicroTurbineFields::MinimumFullLoadElectricalPowerOutput,value);
  }

  //MaximumFullLoadElectricalPowerOutput
  {
    auto value = modelObject.maximumFullLoadElectricalPowerOutput();
    idfObject.setDouble(Generator_MicroTurbineFields::MaximumFullLoadElectricalPowerOutput,value);
  }

  //ReferenceCombustionAirInletTemperature
  {
    auto value = modelObject.referenceCombustionAirInletTemperature();
    idfObject.setDouble(Generator_MicroTurbineFields::ReferenceCombustionAirInletTemperature,value);
  }

  //ReferenceCombustionAirInletHumidityRatio
  {
    auto value = modelObject.referenceCombustionAirInletHumidityRatio();
    idfObject.setDouble(Generator_MicroTurbineFields::ReferenceCombustionAirInletHumidityRatio,value);
  }

  //ReferenceElevation
  {
    auto value = modelObject.referenceElevation();
    idfObject.setDouble(Generator_MicroTurbineFields::ReferenceElevation,value);
  }

  //FuelHigherHeatingValue
  {
    auto value = modelObject.fuelHigherHeatingValue();
    idfObject.setDouble(Generator_MicroTurbineFields::FuelHigherHeatingValue,value);
  }

  //FuelLowerHeatingValue
  {
    auto value = modelObject.fuelLowerHeatingValue();
    idfObject.setDouble(Generator_MicroTurbineFields::FuelLowerHeatingValue,value);
  }

  //StandbyPower
  {
    auto value = modelObject.standbyPower();
    idfObject.setDouble(Generator_MicroTurbineFields::StandbyPower,value);
  }

  //AncillaryPower
  {
    auto value = modelObject.ancillaryPower();
    idfObject.setDouble(Generator_MicroTurbineFields::AncillaryPower,value);
  }

  //ReferenceExhaustAirMassFlowRate
  if( auto value = modelObject.referenceExhaustAirMassFlowRate() )
  {
    idfObject.setDouble(Generator_MicroTurbineFields::ReferenceExhaustAirMassFlowRate,value.get());
  }
  
  //NominalExhaustAirOutletTemperature
  if( auto value = modelObject.nominalExhaustAirOutletTemperature() )
  {
    idfObject.setDouble(Generator_MicroTurbineFields::NominalExhaustAirOutletTemperature,value.get());
  }
  
  /// Choice
  //FuelType
  {
    auto s = modelObject.fuelType();
    idfObject.setString(Generator_MicroTurbineFields::FuelType,s);
  }
  
  
  /// Nodes
  
  // Will leave blank to assume outside air conditions
  //CombustionAirInletNodeName
  idfObject.setString(Generator_MicroTurbineFields::CombustionAirInletNodeName,"");

  //CombustionAirOutletNodeName
  idfObject.setString(Generator_MicroTurbineFields::CombustionAirOutletNodeName,"");

  /// Curves, Not Optional
  //ElectricalPowerFunctionofTemperatureandElevationCurve
  {
    auto curve = modelObject.electricalPowerFunctionofTemperatureandElevationCurve();
    if( auto _curve = translateAndMapModelObject(curve) ) {
      idfObject.setString(Generator_MicroTurbineFields::ElectricalPowerFunctionofTemperatureandElevationCurveName, _curve->name().get());
    }
  }

  //ElectricalEfficiencyFunctionofTemperatureCurve
  {
    auto curve = modelObject.electricalEfficiencyFunctionofTemperatureCurve();
    if( auto _curve = translateAndMapModelObject(curve) ) {
      idfObject.setString(Generator_MicroTurbineFields::ElectricalEfficiencyFunctionofTemperatureCurveName, _curve->name().get());
    }
  }

  //ElectricalEfficiencyFunctionofPartLoadRatioCurve
  {
    auto curve = modelObject.electricalEfficiencyFunctionofPartLoadRatioCurve();
    if( auto _curve = translateAndMapModelObject(curve) ) {
      idfObject.setString(Generator_MicroTurbineFields::ElectricalEfficiencyFunctionofPartLoadRatioCurveName, _curve->name().get());
    }
  }
  /// Curves, Optional

  //AncillaryPowerFunctionofFuelInputCurve
  if( auto curve = modelObject.ancillaryPowerFunctionofFuelInputCurve() )  {
    if( auto _curve = translateAndMapModelObject(curve.get()) ) {
      idfObject.setString(Generator_MicroTurbineFields::AncillaryPowerFunctionofFuelInputCurveName, _curve->name().get());
    }
  }

  //ExhaustAirFlowRateFunctionofTemperatureCurve
  if( auto curve = modelObject.exhaustAirFlowRateFunctionofTemperatureCurve() )  {
    if( auto _curve = translateAndMapModelObject(curve.get()) ) {
      idfObject.setString(Generator_MicroTurbineFields::ExhaustAirFlowRateFunctionofTemperatureCurveName, _curve->name().get());
    }
  }

  //ExhaustAirFlowRateFunctionofPartLoadRatioCurve
  if( auto curve = modelObject.exhaustAirFlowRateFunctionofPartLoadRatioCurve() )  {
    if( auto _curve = translateAndMapModelObject(curve.get()) ) {
      idfObject.setString(Generator_MicroTurbineFields::ExhaustAirFlowRateFunctionofPartLoadRatioCurveName,_curve->name().get());
    }
  }

  //ExhaustAirTemperatureFunctionofTemperatureCurve
  if( auto curve = modelObject.exhaustAirTemperatureFunctionofTemperatureCurve() )  {
    if( auto _curve = translateAndMapModelObject(curve.get()) ) {
      idfObject.setString(Generator_MicroTurbineFields::ExhaustAirTemperatureFunctionofTemperatureCurveName, _curve->name().get());
    }
  }

  //ExhaustAirTemperatureFunctionofPartLoadRatioCurve 
  if( auto curve = modelObject.exhaustAirTemperatureFunctionofPartLoadRatioCurve() )  {
    if( auto _curve = translateAndMapModelObject(curve.get()) ) {
      idfObject.setString(Generator_MicroTurbineFields::ExhaustAirTemperatureFunctionofPartLoadRatioCurveName, _curve->name().get());
    }
  }

  return idfObject;
}
/**
 * Tests whether the ForwarTranslator will handle the name of the GeneratorMicroTurbine correctly in the PlantEquipmentOperationHeatingLoad
 **/
TEST_F(EnergyPlusFixture,ForwardTranslatorGeneratorMicroTurbine_ELCD_PlantLoop)
{

  // TODO: Temporarily output the Log in the console with the Trace (-3) level
  // for debug
  // openstudio::Logger::instance().standardOutLogger().enable();
  // openstudio::Logger::instance().standardOutLogger().setLogLevel(Trace);


  // Create a model, a mchp, a mchpHR, a plantLoop and an electricalLoadCenter
  Model model;

  GeneratorMicroTurbine mchp = GeneratorMicroTurbine(model);
  GeneratorMicroTurbineHeatRecovery mchpHR = GeneratorMicroTurbineHeatRecovery(model, mchp);
  ASSERT_EQ(mchpHR, mchp.generatorMicroTurbineHeatRecovery().get());

  PlantLoop plantLoop(model);
  // Add a supply branch for the mchpHR
  ASSERT_TRUE(plantLoop.addSupplyBranchForComponent(mchpHR));

  // Create a WaterHeater:Mixed
  WaterHeaterMixed waterHeater(model);
  // Add it on the same branch as the chpHR, right after it
  Node mchpHROutletNode = mchpHR.outletModelObject()->cast<Node>();
  ASSERT_TRUE(waterHeater.addToNode(mchpHROutletNode));

  // Create a plantEquipmentOperationHeatingLoad
  PlantEquipmentOperationHeatingLoad operation(model);
  operation.setName(plantLoop.name().get() + " PlantEquipmentOperationHeatingLoad");
  ASSERT_TRUE(plantLoop.setPlantEquipmentOperationHeatingLoad(operation));
  ASSERT_TRUE(operation.addEquipment(mchpHR));
  ASSERT_TRUE(operation.addEquipment(waterHeater));

  // Create an ELCD
  ElectricLoadCenterDistribution elcd = ElectricLoadCenterDistribution(model);
  elcd.setName("Capstone C65 ELCD");
  elcd.setElectricalBussType("AlternatingCurrent");
  elcd.addGenerator(mchp);

  // Forward Translates
  ForwardTranslator forwardTranslator;
  Workspace workspace = forwardTranslator.translateModel(model);

  EXPECT_EQ(0u, forwardTranslator.errors().size());
  ASSERT_EQ(1u, workspace.getObjectsByType(IddObjectType::WaterHeater_Mixed).size());
  ASSERT_EQ(1u, workspace.getObjectsByType(IddObjectType::ElectricLoadCenter_Distribution).size());
  // The MicroTurbine should have been forward translated since there is an ELCD

  WorkspaceObjectVector microTurbineObjects(workspace.getObjectsByType(IddObjectType::Generator_MicroTurbine));
  EXPECT_EQ(1u, microTurbineObjects.size());
  // Check that the HR nodes have been set
  WorkspaceObject idf_mchp(microTurbineObjects[0]);
  EXPECT_EQ(mchpHR.inletModelObject()->name().get(), idf_mchp.getString(Generator_MicroTurbineFields::HeatRecoveryWaterInletNodeName).get());
  EXPECT_EQ(mchpHR.outletModelObject()->name().get(), idf_mchp.getString(Generator_MicroTurbineFields::HeatRecoveryWaterOutletNodeName).get());

  OptionalWorkspaceObject idf_operation(workspace.getObjectByTypeAndName(IddObjectType::PlantEquipmentOperation_HeatingLoad,*(operation.name())));
  ASSERT_TRUE(idf_operation);
  // Get the extensible
  ASSERT_EQ(1u, idf_operation->numExtensibleGroups());
  // IdfExtensibleGroup eg = idf_operation.getExtensibleGroup(0);
   // idf_operation.targets[0]
  ASSERT_EQ(1u, idf_operation->targets().size());
  WorkspaceObject plantEquipmentList(idf_operation->targets()[0]);
  ASSERT_EQ(2u, plantEquipmentList.extensibleGroups().size());

  IdfExtensibleGroup eg(plantEquipmentList.extensibleGroups()[0]);
  ASSERT_EQ("Generator:MicroTurbine", eg.getString(PlantEquipmentListExtensibleFields::EquipmentObjectType).get());
  // This fails
  EXPECT_EQ(mchp.name().get(), eg.getString(PlantEquipmentListExtensibleFields::EquipmentName).get());

  IdfExtensibleGroup eg2(plantEquipmentList.extensibleGroups()[1]);
  ASSERT_EQ("WaterHeater:Mixed", eg2.getString(PlantEquipmentListExtensibleFields::EquipmentObjectType).get());
  EXPECT_EQ(waterHeater.name().get(), eg2.getString(PlantEquipmentListExtensibleFields::EquipmentName).get());

  model.save(toPath("./ForwardTranslatorGeneratorMicroTurbine_ELCD_PlantLoop.osm"), true);
  workspace.save(toPath("./ForwardTranslatorGeneratorMicroTurbine_ELCD_PlantLoop.idf"), true);

}