#include "common.h"

vector_obj* gAlias;

bool extend_alias(char* cmd, char* aliased_cmd)
{
    /// divide into words ///
    vector_obj* words = vector_new(30);
    int words_max = 0;

    bool squote = false;
    bool dquote = false;
    char *p = cmd;
    while(*p) {
        if(*p=='\'') {
            p++;

            char tmp[512];
            char* p2 = tmp;
            *p2++ = '\'';

            while(*p) {
                if(*p == '\'') {
                    *p2++ = *p++;
                    break;
                }
                else 
                    *p2++ = *p++;
            }
            *p2 = 0;

            vector_add(words, STRDUP(tmp));
        }
        else if(*p == '"') {
            p++;

            char tmp[512];
            char* p2 = tmp;
            *p2++ = '"';

            while(*p) {
                if(*p == '"') {
                    *p2++ = *p++;
                    break;
                }
                else 
                    *p2++ = *p++;
            }
            *p2 = 0;

            vector_add(words, STRDUP(tmp));
        }
        else if(*p=='"') {
            dquote = !dquote;
        }
        else if(*p=='&') {
            p++;

            if(*p=='&') {
                p++;

                vector_add(words, STRDUP("&&"));
            }
            else if(*p=='>') {
                p++;

                vector_add(words, STRDUP("&>"));
            }
            else {
                vector_add(words, STRDUP("&"));
            }
        }
        else if(*p=='|') {
            p++;

            if(*p=='|') {
                p++;

                vector_add(words, STRDUP("||"));
            }
            else if(*p=='&') {
                p++;

                vector_add(words, STRDUP("|&"));
            }
            else {
                vector_add(words, STRDUP("|"));
            }
        }
        else if(*p=='>') {
            p++;

            if(*p=='>') {
                p++;

                vector_add(words, STRDUP(">>"));
            }
            else if(*p=='|') {
                p++;

                vector_add(words, STRDUP(">|"));
            }
            else if(*p=='&') {
                p++;

                vector_add(words, STRDUP(">&"));
            }
            else {
                vector_add(words, STRDUP(">"));
            }
        }
        else if(*p=='<') {
            p++;

            if(*p=='<') {
                p++;

                vector_add(words, STRDUP("<<"));
            }
            else if(*p=='>') {
                p++;

                vector_add(words, STRDUP("<>"));
            }
            else if(*p=='&') {
                p++;

                vector_add(words, STRDUP("<&"));
            }
            else {
                vector_add(words, STRDUP("<"));
            }
        }
        else if(*p == ';') {
            p++;

            vector_add(words, STRDUP(";"));
        }
        else if(*p == ' ') {
            p++;

            while(*p == ' ') {
                p++;
            }

            vector_add(words, STRDUP(" "));
        }
        else {
            char word[kAliasMax];
            char* p2 = word;
            while(*p && *p!='&' && *p!='|' && *p!='>' && *p!='<'
                    && *p!=';' && *p!=' ' && *p!='\t')
            {
                *p2++ = *p++;
            }
            *p2 = 0;

            vector_add(words, STRDUP(word));
        }
    }

    /// extend alias ///
    char* p2 = aliased_cmd;
    for(int i=0; i<vector_size(words); i++) {
        char* word = (char*)vector_item(words, i);

        /// expand alias ///
        bool found = false;

        const int len = vector_size(gAlias);
        for(int j=0; j<len; j++) {
            sAlias* alias = (sAlias*)vector_item(gAlias, j);

            if(strcmp(word, alias->mAlias) == 0) {
                found = true;

                if(alias->mArgNum == 0) {
                    char* p3 = alias->mCommand;
                    while(*p3) {
                        *p2++ = *p3++;
                    }
                }
                else {    
                    char* p3 = alias->mCommand;
                    while(*p3) {
                        if(*p3 == '#') {
                            p3++;

                            const int arg_num = *p3 - '0';
                            p3++;

                            int c = i + 1;
                            int count = 0;
                            char* word2;
                            while(c < vector_size(words)) {
                                word2 = (char*)vector_item(words, c);
                                if(strcmp(word2, " ") == 0) {
                                    c++;
                                }
                                else {
                                    if(count == arg_num) {
                                        break;
                                    }

                                    count++;
                                    c++;
                                }
                            }

                            if(c == vector_size(words)) {
                                for(int k=0; k<vector_size(words); k++) {
                                    FREE(vector_item(words, k));
                                }
                                vector_delete(words);
                                return false;
                            }

                            char aliased_command[kAliasMax];
                            if(!extend_alias(word2, aliased_command)) {
                                for(int k=0; k<vector_size(words); k++) {
                                    FREE(vector_item(words, k));
                                }
                                vector_delete(words);
                                return false;
                            }

                            char* p5 = aliased_command;

                            while(*p5) {
                                *p2++ = *p5++;
                            }
                        }
                        else {
                            *p2++ = *p3++;
                        }
                    }

                    int count = 0;
                    while(i < vector_size(words)) {
                        char* word3 = (char*)vector_item(words, i);
                        if(strcmp(word3, " ") == 0) {
                            i++;
                        }
                        else {
                            if(count == alias->mArgNum) {
                                break;
                            }
                            count++;
                            i++;
                        }
                    }
                }

                break;
            }
        }

        /// no alias ///
        if(!found) {
            char* p3 = word;
            while(*p3) {
                *p2++ = *p3++;
            }
        }
    }

    *p2 = 0;

    for(int k=0; k<vector_size(words); k++) {
        FREE(vector_item(words, k));
    }
    vector_delete(words);

    return true;
}

void cmdline_alias_add(char* alias, int arg_num, char* cmd)
{
    sAlias* new_alias = (sAlias*)MALLOC(sizeof(sAlias));

    strcpy(new_alias->mAlias, alias);
    new_alias->mArgNum = arg_num;
    strcpy(new_alias->mCommand, cmd);

    vector_add(gAlias, new_alias);
}

