#include "GLCP.h"
#include "dbimage.h"
#include "bdbenv.h"
#include "dbalnimage.h"
#include "dbtmpfeature.h"
#include <tclap/CmdLine.h>
#include "emcluster.h"
#include "image2d.h"
#include <string>

double distance( double *a, double *b, int sz );
double getshade( image2d &im, int x, int y, int r );
int checkts( double *d );

int checkts( double *d )
{
  for( int i = 0; i < 40; i++ )
    {
      if( isnan( d[i] ) || isinf( d[i] ) )
        {
          std::cout << "time series failed\n";
          exit(0);
        }
    }
  return 0;
}

double distance( double *a, double *b, int sz )
{
  double res;
  res = 0;
  for( int i = 0; i < sz; i++ )
    res = res + pow(a[i]-b[i], 2 );
  return res;
}

double getshade( image2d &im, int x, int y, int r )
{
  double res;
  res = im.getpixel( x, y );
  for( int i = x-r; i < x+r; i++ )
    for( int j = y-r; j < y+r; j++ )
      if( fabs( im.getpixel( i, j ) - res ) > 0.000001 )
        return -1;
  return res;
}

int main( int argc, char *argv[] )
{

#ifndef _NOMAGICK_
  try
    {
      ///set up the command line parsing
      TCLAP::CmdLine cmd("Image alignment program", ' ', "0.001");

      TCLAP::ValueArg< int >
        aid("a", "aid", "tile id", true, 0, "id");
      TCLAP::ValueArg<int> si("i", "id", "image d", true, 0, "0" );
      TCLAP::ValueArg<int> ch("c", "channel", "channel", true, 0, "0" );
      TCLAP::ValueArg<std::string> dbdir("d", "db", "database dirctory", true, "", "databaase");
      TCLAP::ValueArg<std::string> maskfile("m", "mask", "maskimage", true, "", "image");
      TCLAP::ValueArg<std::string> tdbdir( "t", "tmpdb", "temp db", true, "", "tmp db");
      cmd.add(maskfile);
      cmd.add(aid);
      cmd.add(si);
      cmd.add(ch);
      cmd.add(dbdir);
      cmd.add( tdbdir );


      bdbenv bdb;
      bdbenv tmpbdb;
      dbimage imstore;
      dbalnimage dba;
      dbtmpfeature dbtf_g, dbtf_b;

      cmd.parse(argc, argv);

      bdb.open( dbdir.getValue() );
      tmpbdb.open( tdbdir.getValue() );

      imstore.init( bdb.envptr() );
      dba.init( bdb.envptr() );

      dbtf_b.setname( "bad.db" );
      dbtf_g.setname( "good.db" );

      bdb.adddb( &imstore );
      bdb.adddb( &dba );

      bdb.cleanlog();

      int myaid;
      std::cout << "checking aid\n";
      myaid = aid.getValue();

      Magick::Image mask( maskfile.getValue() );
      image2d immask;
      immask.load( mask, CH_GRAY );
      if( dba.checkaid( myaid ) == 1 )
        {
          std::set<int> channels;
          std::cout << "getting channels\n";
          dba.get_channels(myaid, channels );
          std::cout << "checking for valid channel\n";
          int mych;
          mych = ch.getValue();

          if( channels.count( mych ) > 0 )
            {
              image2d im;
              dba.get_aligned_image( myaid, si.getValue(), mych, &im );
              GLCP ss, ss1;
              im.normalize( 0, 256.0/4096.0 );
              Magick::Image mim;

              databuffer dbuff;
              ss.init( &im, 40, 40, 14 );
              ss.serialize( dbuff );
              dbtf_g.setrecsize( dbuff.size() );
              dbtf_b.setrecsize( dbuff.size() );
              dbtf_b.init( tmpbdb.envptr(), 0);
              dbtf_g.init( tmpbdb.envptr(), 0);

              tmpbdb.adddb( &dbtf_g );
              tmpbdb.adddb( &dbtf_b );

              im.getimage( mim );
              mim.write( "blah.png" );
              std::cout << "im max " << im.max() << "\n";
              double *z, *z1;
              z = new double[ 40 ];
              z1 = new double[ 40 ];
              int count;
              count = 0;
              dbuff.clear();
              for( int i = 8; i < im.getheight()-8; i = i + 2 )
                {
                  for( int j = 8; j < im.getwidth()-8; j = j + 2 )
                    {
                      double sh;
                      sh = getshade( immask, i, j, 7 );

                      if( ( sh < 0.25 || sh > 0.75 ) && sh > -0.5 )
                        {
                          if( ss.init( &im, i, j, 14 ) == 0 )
                            {
                              ss.serialize(dbuff);
                              ss1.deserialize(dbuff.getptr(), dbuff.size() );
                              ss.checkequal( ss1 );
                              
                              unsigned int id;
                              if( sh < .25 )
                                {
                                  id = dbtf_b.insert( dbuff.getptr() );
                                }
                              else if( sh > 0.75 )
                                {
                                  id = dbtf_g.insert( dbuff.getptr() );
                                }
                              
                              //ss.print();
                            }
                          count++;
                        }
                    }
                  if( i % 5 == 0 )
                    std::cout << "." << std::flush;
                    
                }

              int mgid, mbid;
              mgid = dbtf_g.maxid();
              mbid = dbtf_b.maxid();
              std::cout << "\n";
              std::cout << "good " << mgid
                        << " bad " << mbid << "\n";
              std::cout << "total " << count << "\n";

              delete [] z;
              delete [] z1;
            }
          else
            {
              std::cout << "invalid channel\n";
            }
        }
      else
        {
          std::cout << "invalid aid\n";
        }
      dbtf_b.close();
      dbtf_g.close();
      dba.close();
      imstore.close();
      bdb.close();
      tmpbdb.close();
    }
  catch (TCLAP::ArgException &e)
    {
      std::cout << "ERROR: " << e.error() 
                << " for arg " << e.argId() << "\n";
      return 0;
    }
  
#else
  std::cout << "compiled with no image magick\n";
#endif
  return 0;
}
