/***************************** LICENSE START ***********************************

 Copyright 2012 ECMWF and INPE. This software is distributed under the terms
 of the Apache License version 2.0. In applying this license, ECMWF does not
 waive the privileges and immunities granted to it by virtue of its status as
 an Intergovernmental Organization or submit itself to any jurisdiction.

 ***************************** LICENSE END *************************************/

//#include <inc_iostream.h>
#include <pwd.h>
//#include <time.h>

#include "Assertions.hpp"
#include "MacroVisitor.h"
#include "MvPath.hpp"
#include "UtilitiesC.h"
#include "SuperPage.h"
#include "Page.h"
#include "ObjectInfo.h"

// --  Static method
// --  Establishes the new macro file Name
string
MacroVisitor::CreateFileName ( const MvRequest& superpageRequest )
{
	// Create an appropriate fileName
	string pathName  = (const char*)ObjectInfo::ObjectPath ( superpageRequest );
	return string(MakeIconName ( pathName.c_str(), "MacroFramework" ));
}

// -- Constructor
//
//    Creates a new Macro file
MacroVisitor::MacroVisitor( string& fileName ):
	outFileName_ ( fileName   )
//	type_        ( type       ),
//	pageId_      ( pageId     )
{
	// Create the temporary file
	tmpFileName_ = MakeTmpName ( "MacroTmp" );

	// Open the output file (the destructor will close it)
	if ( FileCanBeOpened     ( tmpFileName_.c_str(), "w" ) == true )
		filePtr_ = fopen ( tmpFileName_.c_str(), "w" );

	ensure  ( filePtr_ != 0 );

        // Set the Prolog information in the output file
	WriteProlog ();
}

//  -- Destructor
// 
//     Closes the file and performs additional processing
//     (creating an icon or printing)

MacroVisitor::~MacroVisitor()
{
	require ( filePtr_ != 0 );
	
	// Write the trailer information on the file
	this->WriteTrailer ();
		
	fclose ( filePtr_ );  // close the output file

	// Do additional actions, depending on the destination
	// If icon, create description for Metview UI
	string iconFile = MakeIconDescriptionName( outFileName_.c_str() );
	UtWriteIconDescriptionFile ( iconFile.c_str(), "MACRO" );

	// Move temporary file to the output file
	char buf[1024];
	sprintf( buf,"mv '%s' '%s'",tmpFileName_.c_str(),outFileName_.c_str() );
	system(buf);
}

// -- METHOD: WriteProlog
//
// -- PURPOSE: write the header of the macro program
//
void
MacroVisitor::WriteProlog()
{
  struct passwd *who = getpwuid(getuid());
  time_t when = time(NULL);
  const char* version = getenv( "METVIEW_VERSION" );

  fprintf ( filePtr_, "# Metview Macro - created from Display Window contents\n" );
  fprintf ( filePtr_, "# By:   %s\n", version );
  fprintf ( filePtr_, "# Date: %s", ctime(&when) );
  fprintf ( filePtr_, "# For:  %s (%s)\n",who->pw_name, who->pw_gecos );
  fprintf ( filePtr_, "# \n" );
  fprintf ( filePtr_, "# Disclaimer:\n" );
  fprintf ( filePtr_, "#   This macro is to be used primarily as a framework.\n" );
  fprintf ( filePtr_, "#   Some macros generated in this manner may not work\n" );
  fprintf ( filePtr_, "#   as expected and in such cases you may need to\n" );
  fprintf ( filePtr_, "#   fine-tune the macro manually!\n" );
}

// -- METHOD: WriteTrailer
//
// -- PURPOSE: write the final part of the macro program
//
void
MacroVisitor::WriteTrailer()
{
   // Set the device Information
   deviceInfo_.WriteDescription( filePtr_ );

   fprintf(filePtr_,"\n# Drops to SuperPage\n");
   superpageDrops_.WriteDescription ( filePtr_ );

   fprintf(filePtr_,"\n# Drops to Page\n");
   pageDrops_.WriteDescription ( filePtr_ );

   // If there are no drops associated to the pages,
   // we still need to plot something
   if ( pageDrops_.HasAction() == false && superpageDrops_.HasAction() == false )
   {
      // Set build layout function
      fprintf (filePtr_,"# Call function to build layout (defined at end of macro)");
      fprintf (filePtr_,"dw = build_layout()\n");

      // Write the plot command
      fprintf (filePtr_, "plot ( dw )\n");
   }

   fprintf ( filePtr_, "\n# End of main program\n" );

   // Output the page Drops and Contents
   fprintf(filePtr_,"\n# Function to build the layout\n");
   fprintf(filePtr_,"function build_layout()\n\n");

   // Add some indentation since this is now in a function
   pageInfo_.LinePrefix("   ");
   superpageInfo_.LinePrefix("   ");

   pageInfo_.WriteDescription( filePtr_ );

   superpageInfo_.WriteDescription( filePtr_ );
   fprintf(filePtr_,"\nend build_layout\n");
}

// -- METHOD: Visit ( SuperPage& )
//
// -- PURPOSE: Visit a superpage and retrieve its creation request,
//			   name, and all dataunits and visdefs associated to it
//             

void 
MacroVisitor::Visit ( SuperPage& superpage )
{
   macroName_ = superpage.MacroName();

   superpage.DescribeDevice ( deviceInfo_ );

   superpage.DescribeYourself ( superpageInfo_ );

   superpage.DescribeDrops ( superpageDrops_,vdMap_ );
}

// -- METHOD: Visit ( Page& )
//
// -- PURPOSE: Visit a page and retrieve its creation request,
//	name, and all dataunits and visdefs associated to it
//
void 
MacroVisitor::Visit ( Page& page)
{
   // Print the contents of the page 
   page.DescribeYourself ( pageInfo_  );

   // PrintData Units and VisDefs
   page.DescribeDrops    ( pageDrops_, vdMap_ );
}

void 
MacroVisitor::Visit ( SubPage& )
{
   // Empty
}
