/**
 * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
 *
 * Please see distribution for license.
 */
package com.opengamma.integration.tool.portfolio;

import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;

import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.component.tool.AbstractTool;
import com.opengamma.financial.tool.ToolContext;
import com.opengamma.integration.copier.portfolio.PortfolioCopier;
import com.opengamma.integration.copier.portfolio.PortfolioCopierVisitor;
import com.opengamma.integration.copier.portfolio.QuietPortfolioCopierVisitor;
import com.opengamma.integration.copier.portfolio.SimplePortfolioCopier;
import com.opengamma.integration.copier.portfolio.VerbosePortfolioCopierVisitor;
import com.opengamma.integration.copier.portfolio.reader.MasterPortfolioReader;
import com.opengamma.integration.copier.portfolio.reader.PortfolioReader;
import com.opengamma.integration.copier.portfolio.rowparser.JodaBeanRowParser;
import com.opengamma.integration.copier.portfolio.rowparser.RowParser;
import com.opengamma.integration.copier.portfolio.writer.PortfolioWriter;
import com.opengamma.integration.copier.portfolio.writer.PrettyPrintingPortfolioWriter;
import com.opengamma.integration.copier.portfolio.writer.SingleSheetSimplePortfolioWriter;
import com.opengamma.integration.copier.portfolio.writer.ZippedPortfolioWriter;
import com.opengamma.integration.copier.sheet.SheetFormat;
import com.opengamma.util.generate.scripts.Scriptable;

/**
 * The portfolio saver tool
 */
@Scriptable
public class PortfolioSaverTool extends AbstractTool<ToolContext> {

  /** File name option flag */
  private static final String FILE_NAME_OPT = "f";
  /** Portfolio name option flag*/
  private static final String PORTFOLIO_NAME_OPT = "n";
  /** Write option flag */
  private static final String WRITE_OPT = "w";
  /** Verbose option flag */
  private static final String VERBOSE_OPT = "v";
  /** Asset class flag */
  private static final String SECURITY_TYPE_OPT = "s";

  private static ToolContext s_context;
  
  //-------------------------------------------------------------------------
  /**
   * Main method to run the tool.
   * 
   * @param args  the arguments, not null
   */
  public static void main(String[] args) { //CSIGNORE
    new PortfolioSaverTool().initAndRun(args, ToolContext.class);
    System.exit(0);
  }

  //-------------------------------------------------------------------------
  /**
   * Loads the test portfolio into the position master.
   */
  @Override 
  protected void doRun() {     
    s_context = getToolContext();

    // Construct portfolio reader
    PortfolioReader portfolioReader = constructPortfolioReader(
        getCommandLine().getOptionValue(PORTFOLIO_NAME_OPT)
    );

    // Create portfolio writer
    PortfolioWriter portfolioWriter = constructPortfolioWriter(
        getCommandLine().getOptionValue(FILE_NAME_OPT), 
        getCommandLine().getOptionValue(SECURITY_TYPE_OPT),
        getCommandLine().hasOption(WRITE_OPT)
    );
    
    // Construct portfolio copier
    PortfolioCopier portfolioCopier = new SimplePortfolioCopier();
        
    // Create visitor for verbose/quiet mode
    PortfolioCopierVisitor portfolioCopierVisitor; 
    if (getCommandLine().hasOption(VERBOSE_OPT)) {
      portfolioCopierVisitor = new VerbosePortfolioCopierVisitor();
    } else {
      portfolioCopierVisitor = new QuietPortfolioCopierVisitor();
    }
    
    // Call the portfolio loader with the supplied arguments
    portfolioCopier.copy(portfolioReader, portfolioWriter, portfolioCopierVisitor);

    // close stuff
    portfolioReader.close();
    portfolioWriter.close();
  }
  
  private static PortfolioWriter constructPortfolioWriter(String filename, String securityType, boolean write) {
    if (write) {  
      // Check that the file name was specified on the command line
      if (filename == null) {
        throw new OpenGammaRuntimeException("File name omitted, cannot export to file");
      }
       
      if (SheetFormat.of(filename) == SheetFormat.CSV || SheetFormat.of(filename) == SheetFormat.XLS) {
//        if (securityType.equalsIgnoreCase("exchangetraded")) {
//          return new SingleSheetSimplePortfolioWriter(filename, new ExchangeTradedRowParser(s_context.getBloombergSecuritySource()));
//        } else {
        
        RowParser rowParser = JodaBeanRowParser.newJodaBeanRowParser(securityType);
        if (rowParser != null) {
          return new SingleSheetSimplePortfolioWriter(filename, rowParser);
        } else {
          throw new OpenGammaRuntimeException("Could not create a row parser for security type " + securityType);
        }
//        }
      } else if (SheetFormat.of(filename) == SheetFormat.ZIP) {
        return new ZippedPortfolioWriter(filename);
      } else {
        throw new OpenGammaRuntimeException("Input filename should end in .CSV, .XLS or .ZIP");
      }

    } else {      
      // Create a dummy portfolio writer to pretty-print instead of persisting
      return new PrettyPrintingPortfolioWriter(true);
    }
  }

  private static PortfolioReader constructPortfolioReader(String portfolioName) {
    return new MasterPortfolioReader(
        portfolioName, s_context.getPortfolioMaster(), 
        s_context.getPositionMaster(), 
        s_context.getSecuritySource()
    );
  }

  @Override
  protected Options createOptions(boolean contextProvided) {
    
    Options options = super.createOptions(contextProvided);

    Option filenameOption = new Option(
        FILE_NAME_OPT, "filename", true, "The path to the file to create and export to (CSV, XLS or ZIP)");
    filenameOption.setRequired(true);
    options.addOption(filenameOption);
    
    Option portfolioNameOption = new Option(
        PORTFOLIO_NAME_OPT, "name", true, "The name of the source OpenGamma portfolio");
    options.addOption(portfolioNameOption);
    
    Option writeOption = new Option(
        WRITE_OPT, "write", false, 
        "Actually persists the portfolio to the file if specified, otherwise pretty-prints without persisting");
    options.addOption(writeOption);
       
    Option assetClassOption = new Option(
        SECURITY_TYPE_OPT, "securitytype", true, 
        "The security type to export (ignored if ZIP output file is specified)");
    options.addOption(assetClassOption);
    
    Option verboseOption = new Option(
        VERBOSE_OPT, "verbose", false, 
        "Displays progress messages on the terminal");
    options.addOption(verboseOption);

    return options;
  }

}

@@ -2055,16 +2055,101 @@
 T = %22s%22;
+%0A  /** Include trades flag */%0A  private static final String INCLUDE_TRADES_OPT = %22t%22;
 %0A%0A  priv
@@ -3147,24 +3147,80 @@
 n(WRITE_OPT)
+,%0A        getCommandLine().hasOption(INCLUDE_TRADES_OPT)
 %0A    );%0A    
@@ -3975,16 +3975,97 @@
 an write
+,%0A                                                          boolean includeTrades
 ) %7B%0A    
@@ -4805,16 +4805,31 @@
 owParser
+, includeTrades
 );%0A     
@@ -5089,16 +5089,31 @@
 filename
+, includeTrades
 );%0A     
@@ -6788,24 +6788,24 @@
 terminal%22);%0A
-
     options.
@@ -6827,24 +6827,242 @@
 seOption);%0A%0A
+    Option includeTradesOption = new Option(%0A        INCLUDE_TRADES_OPT, %22trades%22, false,%0A        %22Generate a separate row for each trade instead of one row per position%22);%0A    options.addOption(includeTradesOption);%0A%0A
     return o

Allow the portfolio saver tool to handle multi-trade positions by optionally emitting one row per trade (-t option) rather than emitting one row per position as usual. The portfolio loader tool will be able to load multi-trade positions that were exported in this way, with its soon-to-be-added merge positions option.