// Prescribble reader


#include "prescribblereader.hpp"
#include <string>
#include <iostream>
#include <fstream>
#include <cstdio>

PrescribbleReader::PrescribbleReader(PresNoteConfig &a_config,
                                     PrescribbleNoteListener *a_pListener)
    : m_config(a_config ), m_pListener( a_pListener )
{
}

/**
 * reads in notes from file
 */
bool PrescribbleReader::loadInto( const char *filename, NotesVector &a_notes )
{

    //setFeedbackLabel("loading XML");
    // clear out the old first?
    std::ifstream in( filename );
    std::string s;

    bool appending = false;
    //if(DEBUG)printf("reading...\n");
    while( in >> s ){
        //std::cout<<"read:'"<<s<<"'\n";
        if( 0==s.compare( Pres::STROKE_TAG_BEGIN ) )
        {
            appending = false;
            
        }
        else if( 0==s.compare( Pres::STROKE_TAG_END ) )
            ;
        
        
        else if( 0==s.compare( Pres::NOTE_TAG_BEGIN ) )
        {
            PrescribbleNote *p = new PrescribbleNote(m_config, m_pListener);
            a_notes.push_back( p );
            //m_pArea->setCurrentNote( p );
            
        }
        else if( 0==s.compare( Pres::NOTE_TAG_END ) )
            ;
        
        else if( 0==s.compare( Pres::NOTEBOOK_TAG_BEGIN ) )
        {
            ;
        }
        else if( 0==s.compare( Pres::NOTEBOOK_TAG_END ) )
            ;

        else {
            //printf("hi?\n");
            char *endptr;
            long l1 = std::strtol( s.c_str(), &endptr, 10);
            long l2 = std::strtol( endptr+1, &endptr, 10);
            
            //std::cout<<" number:"<<l1<<","<<l2<<"\n" ;
            Point2D p( (int)l1, (int)l2 );
            if(appending)
                a_notes.back()->continueStroke( p );
            else
                a_notes.back()->beginStroke( p );
            appending = true;
        }
    }
//    if(DEBUG)printf("reading..done!!\n");
           

    return true;

}

//=========================================

#if USE_EXPAT
#include <expat.h>
#endif

/**
 * this code borrowed from loader.cxx in the keyboard app for
 * the Agenda VR3
 */
void decodeutf8string(char* o, char* i) {
	while(*i) {
		if((*i & 0x80) == 0) {
			*o = *i;
			o++;
			i++;
		}
		else if((*i & 0xE0) == 0xC0) {
			*o = ((*i & 0x03) << 6) | (*(i+1) & 0x3F);
			o++;
			i+=2;
		}
		else {
			*o = 0;
			o++;
			i++;
			while((*i & 0xC0) == 0x80) {
				i++;
			}
		}		
	}
	*o = 0;
}



PrescribbleXMLReader::PrescribbleXMLReader( PresNoteConfig &a_config, 
                                            PrescribbleNoteListener *a_pListener)
    : PrescribbleReader(a_config, a_pListener )
{
}

/**
 * reads in notes from file
 */
bool PrescribbleXMLReader::loadInto( const char *filename, 
                                     NotesVector &a_notes )
{
    m_pNotes = &a_notes;

#if USE_EXPAT
    char buf[1024];
    XML_Parser parser = XML_ParserCreate(NULL);
    int done;
    XML_SetElementHandler(parser, &start_cb, &end_cb);
    XML_SetCharacterDataHandler(parser, &data_cb);
    XML_SetUserData( parser, this );
    FILE* fp;
	
	fp = fopen(filename, "r");
	if (fp != NULL) {
            do {
                size_t len = fread(buf, 1, sizeof(buf), fp);
                done = len < sizeof(buf);
                if (!XML_Parse(parser, buf, len, done)) {
                    fprintf(stderr, "%s at line %d\n", 
                            XML_ErrorString(XML_GetErrorCode(parser)), 
                            XML_GetCurrentLineNumber(parser));
                }
            } while (!done);
            fclose(fp);
	}
	XML_ParserFree(parser);	
        return true;
#else
        return PrescribbleReader::loadInto( filename, a_notes );
//        return false;
#endif

}


void PrescribbleXMLReader::processStringData()
{
    std::istrstream in( m_strData.c_str(), m_strData.size() );
    std::string s;
    while( in >> s ){
            char *endptr;
            long l1 = std::strtol( s.c_str(), &endptr, 10);
            long l2 = std::strtol( endptr+1, &endptr, 10);
            
            //std::cout<<" number:"<<l1<<","<<l2<<"\n" ;
            Point2D p( (int)l1, (int)l2 );
            //std::printf("   Point2D( %i, %i )\n",p.x, p.y );
            if(m_appending)
                m_pNotes->back()->continueStroke( p );
            else
                m_pNotes->back()->beginStroke( p );
            m_appending = true;
    }
    m_strData = "";
}

void PrescribbleXMLReader
::start_cb(void *userData, const char *name, const char **atts)
{
    PrescribbleXMLReader *a_this 
        = static_cast<PrescribbleXMLReader*>(userData);
 
  // std::printf("<%s>\n",name);

    if(strcasecmp(name, "notebook" )==0){


    }
    else if(strcasecmp(name, "stroke" )==0){
        a_this->m_appending = false;
        a_this->m_strData == "";
    }
    else if(strcasecmp(name, "note" )==0){
        PrescribbleNote *p = new PrescribbleNote(a_this->m_config, a_this->m_pListener);
        a_this->m_pNotes->push_back( p );
    }


}

void PrescribbleXMLReader
::data_cb(void *userData, const char *data, int len)
{
    PrescribbleXMLReader *a_this 
        = static_cast<PrescribbleXMLReader*>(userData);

    //char *x = new char[len+1];
    //std::printf(" text->%i<-\n",len);

    a_this->m_strData.append( data, len );
    

}


void PrescribbleXMLReader
::end_cb(void *userData, const char *name)
{
//    std::printf("</%s>\n",name);
 
   PrescribbleXMLReader *a_this 
        = static_cast<PrescribbleXMLReader*>(userData);
 

   //if(strcasecmp(name, "notebook" )==0){
   //}
   // else 
   if(strcasecmp(name, "stroke" )==0){
       a_this->processStringData();
   }



}

