#include "AsxReader.h"

#include <ctype.h>
#include <iostream>

using namespace std;

enum asx_position
{
    open_bracket,
    close_bracket,
    in_comment,
    in_quoted_comment,
    in_tagname,
    after_tagname,
    in_endtag,
    before_tagclose,
    in_propname,
    after_propname,
    prop_equal,
    after_propequal,
    between_props,
    in_propcontents,
    in_quoted_propcontents,
    in_quoted_contents,
    in_contents
};

inline bool is_whitespace(char c)
{
    return ((c==' ') || (c=='\t') || (c=='\r') || (c=='\n'));
}

bool ASX_Reader::create(const vector<char>& data)
{
    string last_tag;
    string last_prop;
    string last_prop_val;
    int last_start=0;
    if(data.size()==0)return false;
    if(data[0]!='<')return false;
    asx_position state=open_bracket;
    for(unsigned i=1; i<data.size(); i++)
    {
	char c=data[i];
	bool is_alpha=isalpha(c);
	bool is_space=is_whitespace(c);
	switch(state)
	{
	case open_bracket:
	    if(is_space)continue;
	    if(c=='/')
	    {
		state=in_endtag;
		last_start=i+1;
		continue;
	    }
	    if(c=='!')
	    {
		state=in_comment;
		continue;
	    }
	    if(is_alpha)
	    {
		state=in_tagname;
		last_start=i;
		continue;
	    }
	    cout<<i<<endl;
	    return false;
	case in_comment:
	    if(c=='"')
		state=in_quoted_comment;
	    if(c=='>')
		state=close_bracket;
	    continue;
	case in_quoted_comment:
	    if(c=='"')
		state=in_quoted_comment;
	    continue;
	case close_bracket:
	    if(c=='<')
	    {
		state=open_bracket;
		continue;
	    }
	    state=in_contents;
	    continue;
	case in_tagname:
	    if(is_space)
	    {
		last_tag=string(&data[last_start], i-last_start);
//		cout<<"TAG: "<<last_tag<<endl;
		state=after_tagname;
	    }
	    if((c=='/')||(c=='>'))
	    {
		last_tag=string(&data[last_start], i-last_start);
//		cout<<"TAG: "<<last_tag<<endl;
		if(c=='/')
	    	    state=before_tagclose;
		else
		    state=close_bracket;
	    }
	    continue;
	case after_tagname:
	    if(is_space) continue;
	    if(c=='/')
	    {
		state=before_tagclose;
		continue;
	    }
	    state=in_propname;
	    last_start=i;
	    continue;
	case in_endtag:
	    if(c=='>')
	    {
		state=close_bracket;
		last_tag=string(&data[last_start], i-last_start);
//		cout<<"/TAG: "<<last_tag<<endl;
		if(strcasecmp(last_tag.c_str(), "asx")==0)
		    return true;
	    }
	    continue;
	case before_tagclose:
	    if(is_space)continue;
	    if(c=='>')
	    {
		state=close_bracket;
		continue;
	    }
//	    cout<<"before_tagclose:"<<i<<endl;
	    return false;
	case in_propname:
	    if(c=='=')
	    {
		last_prop=string(&data[last_start], i-last_start);
//		cout<<"PROPERTY: "<<last_prop<<endl;
		state=prop_equal;
	    }
	    if(is_space)
	    {
		last_prop=string(&data[last_start], i-last_start);
//		cout<<"PROPERTY: "<<last_prop<<endl;
		state=after_propname;
	    }
	    continue;
	case after_propname:
	    if(c=='=')
		state=prop_equal;
	    continue;
	case prop_equal:
	    if(is_space)
		continue;
	    if(c=='"')
		state=in_quoted_propcontents;
	    else
	        state=in_propcontents;
	    last_start=i;
	    continue;
	case in_propcontents:
	    if(c=='"')
	    {
		state=in_quoted_propcontents;
		continue;
	    }
	    if(is_space || (c=='/') || (c=='>'))
	    {
		last_prop_val=string(&data[last_start], i-last_start);
//		cout<<"VALUE: "<<last_prop_val<<endl;
		if(strcasecmp(last_tag.c_str(), "ref")==0)
		    if(strcasecmp(last_prop.c_str(), "href")==0)
		    {
			cout<<"Href: "<<last_prop_val<<endl;
			if(last_prop_val.size())
			    if(last_prop_val[0]=='"')
				last_prop_val.erase(0, 1);
			if(last_prop_val.size())
			    if(last_prop_val[last_prop_val.size()-1]=='"')
				last_prop_val.erase(last_prop_val.size()-1, 1);
			m_Urls.push_back(last_prop_val);
		    }
		switch(c)
		{
		case '/':
		    state=before_tagclose;
		    break;
		case '>':
		    state=close_bracket;
		    break;
		default:
		    state=between_props;
		    break;
	        }
	    }
	    continue;
	case in_quoted_propcontents:
	    if(c=='"')
	    {
		state=in_propcontents;
		continue;
	    }
	    continue;
	case between_props:
	    if(is_space)
		continue;
	    if(c=='/')
	    {
		state=before_tagclose;
		continue;
	    }
	    else if(c=='>')
	    {
	        state=close_bracket;
		continue;
	    }
	    if(is_alpha)
	    {
		last_start=i;
		state=in_propname;
		continue;
	    }
//	    cout<<"between_props:"<<i<<endl;
	    return false;
	case in_contents:
	    if(c=='"')
		state=in_quoted_contents;
	    if(c=='<')
		state=open_bracket;
	    continue;
	case in_quoted_contents:
	    if(c=='"')
		state=in_contents;
	    continue;
	default: // after_propequal
            cout << "FIXME ERROR after_propequal not handled" << endl;
            break;
	}
    }
    return true;
}
