#include <iostream>
#include <sstream>
#include <string>
#include <fstream>
#include <map>

using namespace std;

/*
Notes: 

Limited parsing support for quoted
 text.

A command line constructed from a
 string is different from a command
 line constructed from the actual
 command line because of the shell.

This is bad but as the command line
 is so useful I have worked around
 by providing a subset of 1 level
 quoting.

It could rightly be argued that I did
 it in the wrong place, instead
 of read(string&) i did it in 
 read(istream&).  

Not sure about readfile. 
*/


#include <commandline.h>


bool splitstring
(
  string& sleft,
  string& sright,
  stringc & s,
  char const delim
);

void readToMap(map<string,string>& m, int argc, char **argv);
void writeMap(string& s, map<string,string> const & m);

void commandline::readfile( stringc var )
{
  if (var.empty())
    return;

  string file;
  mapvar(file,var.c_str());
  if (!file.empty())
  {
    ifstream f1(file.c_str());
    read(f1);
  }
}


commandline::commandline(int argc, char** argv)
{ 
  for (uint i=1; i<(uint)argc; ++i)
  {
    string s1, s2;
    if (splitstring(s1,s2,string(argv[i]),'='))
    {
      mp[s1] = s2;
//cout << "*** s2=*" << s2 << "*" << endl;
//cout << "*** mp[s1]=*" << mp[s1] << "*" << endl;
    }
    else
      tokens.insert(argv[i]);
    args.push_back(argv[i]);
  }
}

void commandline::read(stringc & arg)
{
  stringstream ss(arg);
  read(ss);

//cout << SHOW(arg) << endl;
//  assert(false);
}

/*
void commandline::read(istream & is )
{
  string s;
  char ch='';
  if (is.eof()==false)
    is >> ch;

  for (; is.eof()==false; )
  {
    s += ch;
    is >> ch;
  }

  read(s);
}
*/
    
    

void commandline::read(istream & is )
{
  string s;
  args.clear();
  vector<string>& vi(args);

  if (is.eof()==false)
    is >> s;

  for (; is.eof()==false; )
  {
    vi.push_back(s);
    s.clear();
    is >> s;
  }
  if (s.size()!=0)
    vi.push_back(s);
  
//  for (uint i=0; i<vi.size(); ++i)
//  {
//cout << "*vi[" << i << "]=" <<  vi[i] << "*" << endl;
//  }

//Converting v to v2
//*vi[0]=s1=abc*
//*vi[1]=points="1*
//*vi[2]=19*
//*vi[3]=32*
//*vi[4]=4"*
//*vi[5]=N=350*
//*v2[0]=s1=abc*
//*v2[1]=points=1 19 32 4*
//*v2[2]=N=350*

  if (vi.size()==0)
    return;

  vector<string> v2;
  bool quote=false;
  
  string::size_type k;
  for (uint i=0; i<vi.size(); ++i)
  { 
    string current(vi[i]);
    k = current.find('"');
 
    // Looking for closing quote
    if (quote)
    {
      if(k!=string::npos)    
      {
        current.erase(k,1);
        quote=false;
      }      
      v2[v2.size()-1] += (string(" ")+current);
    }
    else
    {
      if (k!=string::npos)
      {
        current.erase(k,1);
        quote=true;
      } 
      v2.push_back(current);
    }  
  }

//  for (uint i=0; i<v2.size(); ++i)
//  {
//cout << "*v2[" << i << "]=" <<  v2[i] << "*" << endl;
//  }


  // Now do parsing
  for (uint i=0; i<v2.size(); ++i)
  {
    string s1, s2;
    if (splitstring(s1,s2,v2[i],'='))
      mp[s1] = s2;
    else
      tokens.insert(v2[i]);
  }
}


commandline::commandline(stringc & arg)
{
  read(arg);
}

commandline::commandline(istream & is)
{
  read(is);
}

ostream & commandline::enablehelp(ostream & os) const
{
  stringc hlp("-h");

  boolc hflag = (tokens.find(hlp)!=tokens.end());
  if (hflag)
  {
    for (uint i=0; i<bindvar.size(); ++i)
      os << bindvar[i] << " ";
    os << endl;
  }

  return os;
}


void readToMap(map<string,string>& m, int argc, char **argv)
{
  for (uint i=1; i<(uint)argc; ++i)
  {
    string s1, s2;
    if (splitstring(s1,s2,string(argv[i]),'='))
      m[s1] = s2;
   }
}


// <TODO> Make delimit a string so function is more general, 
// CE Friday 9th November 2001
//

bool splitstring
(
  string& sleft, 
  string& sright, 
  stringc& s, 
  const char delim 
)
{
//cout << "s=*" << s << "*" << endl;

  string::size_type k = s.find(delim);
  uint len = s.length();
  if (k<1 || (k>=len-1) || len==0)
    return false;

  sleft = s;
  sleft.erase(k);
  sright = s;
  sright.erase(0,k+1);

//cout << "sright=*" << sright << "*" << endl;

  return true;
}


void writeMap(string& s, const map<string,string>& m)
{
  string s2;
  map<string,string>::const_iterator i=m.begin();
  for(;i!=m.end();++i)
    s2 += (i->first + "=" + i->second + " ");

  s = s2;
}




