#include "head.h" 

int queryinput(int *x, int *inquery, int *query){
    setlocale(LC_ALL, "");

    //INPUT-------------------------------------------------
    wint_t ch;
    *inquery = 0;
    while((ch=getwchar())!=L'\n'&&ch!=L'\t'&&ch!=L' '&&*inquery<QUERYMAX){
        *(query+*inquery)=(int)ch;
        (*inquery)++;
    }
    //______________________________________________________

    if(ch == WEOF)return -1;    

    //COUNT -------------------------------------------------
    int c=0;

    if(ch==L'\n')x[2]++;
    else if(ch==L'\t')x[3]++;
    else if(ch==L' ')x[4]++;

    while (c < *inquery)
    {
        int sym = query[c];
        if ((sym >= L'а' && sym <= L'я') ||
            (sym >= L'А' && sym <= L'Я'))
        {
            x[0]++;
            c++;
            continue;
        }
        if (sym >= L'0' && sym <= L'9')
        {
            x[1]++;
            c++;
            continue;
        }
        if (sym > 32 && sym <= 47) {
           x[sym - 28]++;
            c++;
            continue;
        }
        if (sym > 58 && sym <= 64) {
            x[sym - 38]++;
            c++;
            continue;
        }
        x[33]++;
        c++;
    }
    //________________________________________________________


    return 0;
}

void func1 (char **f, int *x,int inquery, int *query){
    switch(funcReturn(f[2])){
        case 1://Определяет среднюю длину слова в тексте
        {
            if(x[32]){
                x[30]/=x[31];
                printf("\n\tСредняя длинна слова - %d",x[30]);
            }
            else{
                x[30]+=inquery;
                x[31]++;
                }
            break;
        }

        case 2://Подсчитывает количество слов, длина которых не превышает 5 символов.
        {
            if(x[32]){
                printf("\n\tВсего слов <5 букв - %d",x[30]);
            }
            else if(inquery<5)x[30]++;
            break;
        }

        case 3://Определяет количество букв после первого и до последнего слова.
        {
            if(x[31]);
            else {x[30]-=x[0];x[31]=1;}
            if(x[32]){x[30]+=x[0];printf("\n\tКолл-во букв после 1 и до последнего слова - %d",x[30]);}
            break;
        }
        case 4://Удаляет первую букву каждого слова и выводит результат.
        {   
            if(x[32]);
            else
            put(x,1,inquery,query);
            break;
        }

        case 5://определяет, сколько в заданном тексте слов, начинающихся с буквы,заданной пользователем.
        {
            if(x[32])
                printf("\n\t Слов начинающихся на %c - %d",f[4][0],x[30]);
            else
                if(query[0]==f[3][0])x[30]++;
            break;
        }
        case 6://находит сумму всех цифр в введенном предложении. (если в тексте нетцифр, добавить) предусмотреть обработку шаблонов (12word, wo12rd,word12)
        {
            if(x[32])
                printf("\n\t Найти сумму всех цифр - %d",x[31]);
            else
                for(int i=0;i<inquery;i++){
                    if(query[i]>=L'0'&&query[i]<=L'9'){
                        x[30]=(x[30]*100)+(query[i]-L'0');
                    }
                }
            x[31]+=x[30];
            x[30]=0;
            break;
        }

        case 7:// вставляет восклицательный знак в конце каждой строки текста.
        {
            if(x[32]);
            else{
                if(query[inquery-1]==L'\n'){
                    if(query[inquery-2]==L'!'||query[inquery-2]==L'?'||query[inquery-2]==L'.'||query[inquery-2]==L',')
                        query[inquery-2]=L'!';
                    else {query[inquery-1]=L'!';query[inquery]=L'\n';}
                    x[L'!'-28]++;inquery++;}
                put(x,0,inquery,query);
            }
            break;
        }

        case 8://проверяет заканчивается ли каждая строка точкой и добавляет ее при необходимости, считает сколько точек было добавлено
        {
            if(x[32]);
            else{
                if(query[inquery-1]==L'\n'){
                    if(query[inquery-2]==L'!'||query[inquery-2]==L'?'||query[inquery-2]==L'.'||query[inquery-2]==L',')
                        query[inquery-2]=L'.';
                    else {query[inquery-1]=L'.';query[inquery]=L'\n';}
                    x[L'!'-28]++;inquery++;}
                put(x,0,inquery,query);
            }
            break;
        }

        case 9://определяет сколько раз в введенной строке встречается слово,заданное пользователем.
        {
            if(x[32])
                printf("\n\t Слово %s встречается - %d раз",f[4],x[30]);
            else{
                if(last(inquery,query))inquery--;
                x[30]+=strquery(f[3],query);}
            break;
        }

        case 10://подсчитывает количество букв в каждом втором слове.
        {
            x[34] = x[0] - x[33];
            if(x[32]){
                x[31]=x[33]-x[31];
                printf("\n\t Сумма букв в четных словах - %d",x[31]);
                }
            else{
                if(x[30]%2==0)
                    x[31]+=x[34];
                x[33]+=x[33];
                x[30]++;
            }
            break;
        }
    }
}

void func2 (char **f, int *x,int inquery, int *query,int *ch){
    switch(funcReturn(f[2])){
        case 1: //Подсчитывает, сколько слов начинается с последней буквы первого слова.
        {
            if(x[32]){
                printf("\n\t Количество букв начинающихся с %c - %d",x[32],x[34]);
            }
            else if(!(x[31])){x[31]=0;x[33]=query[inquery-1];}
            else{if (query[0]==x[33]){x[34]++;}}
            break;
        }
        case 2: //Подсчитывает, сколько слов имеют указанную пользователем длину.
        {
            if(x[32])printf("\n\t Слов имеющих указанную длинну - %d",x[30]);
            else{
                if(last(inquery,query))inquery--;
                if(strquery(f[3],query))x[30]++;
            }
            break;
        }
        case 3: //Печатает самое длинное слово в тексте.
        {
            if(x[32]){printf("\n\t");}
            else{
                if(x[31]<inquery){
                    for(int i = 0;i<inquery;i++)
                        ch[i]=query[i];
                    x[31]=inquery;
                }   
            }
            break;
        }
        case 4: //Подсчитывает количество знаков препинания (не букв и не цифр).
        {
            if(x[32]){printf("\n\tЗнаков препинания: %d",x[5]+x[16]+x[18]+x[25]);}
            break;
        }
        /*case 5: //Сортирует текст в порядке возрастания
        {
            break;      Я хз что с этим делать
        }*/
        case 6: // Находит слова с тире во введенном тексте.
        {
            if(x[28]);
            else{
                for(int i = 0;i<inquery;i++){
                    if(query[i]==L'-'&&inquery>1){
                        x[30]=x[2];
                        x[31]=x[3];
                        x[33]=x[4];
                        put(x,0,inquery,query);
                        break;
                    }
                }
            }
            break;
        }
        case 7: //Вычисляет количество слов между первой и последней запятой во введенном тексте
        {
            if(x[32]){printf("\n\tКолличество слов между первой и последней запятой - %d",x[34]);}
            else{
                if(x[L','-28]>0){
                    x[31]+=inquery;
                    if(x[L','-28]>x[33]){
                        x[34]+=x[31];
                        x[33]=x[31];
                        x[31]=0;
                    }
                }
            }
            break;
        }
        case 8: //Находит два соседних слова, начинающихся с большой буквы
        {
            if(x[28]);
            else{
                if(*query>=L'А'&&*query<=L'Я'){
                    x[35]++;
                    if(x[35]==2){
                        x[30]=x[2];
                        x[31]=x[3];
                        x[33]=x[4];
                        x[35]=0;
                        printf("\n\t");
                        put(x,0,x[34],ch);
                        printf(" - ");
                        put(x,0,inquery,query);
                        printf(" | Находятся друг за другом");
                    }
                    for(int i = 0;i<inquery;i++)ch[i]=query[i];
                    x[34]=inquery;
                } 
                else {x[35] = 0;}
            }
            break;
        }
        /*case 9: //Сортирует строку в тексте по убыванию
        {
                        Я снова хз
            break;
        }*/
        case 10://Заменяет в каждом слове повторяющиеся буквы на L'–'
        {
            if(x[32]);
            else{
            for(int i=0;i<inquery;i++){
                for(int j=0;j<inquery;j++)
                    if(query[j]==query[i])query[j]=query[i]=L'-';
            }
                put(x,0,inquery,query);
            }
            break;
        }
    }
}


void func3 (char **f, int *x,int inquery, int *query){
    int alphabet[33*2] = {
        L'а',L'б',L'в',L'г',L'д',L'е',L'ё',L'ж',L'з',L'и',L'й',L'к',L'л',L'м',L'н',L'о',
        L'п',L'р',L'с',L'т',L'у',L'ф',L'х',L'ц',L'ч',L'ш',L'щ',L'ъ',L'ы',L'ь',L'э',L'ю',L'я',
        L'А',L'Б',L'В',L'Г',L'Д',L'Е',L'Ё',L'Ж',L'З',L'И',L'Й',L'К',L'Л',L'М',L'Н',L'О',
        L'П',L'Р',L'С',L'Т',L'У',L'Ф',L'Х',L'Ц',L'Ч',L'Ш',L'Щ',L'Ъ',L'Ы',L'Ь',L'Э',L'Ю',L'Я'
    };

    switch(funcReturn(f[2])){
        case 1: //Реверсирует слово. Пример: Привет ->тевирП
        {
            put(x,inquery-1,0,query);
            break;
        }
        case 2: //Делит слово на два и меняет начало с концом. Пример: жук -> кжу,солнце -> нцесол
        {
            put(x,0,inquery/2,query);
            put(x,inquery/2,inquery,query);
            break;
        }
        case 3: //После каждой гласной буквы вставляется буква L'c' и гласная повторяется. Пример: кот ->косот.
        {
            int alph[20] = {L'а',L'и',L'е',L'ё',L'о',L'у',L'ы',L'э',L'ю',L'я',
                            L'А',L'И',L'Е',L'Ё',L'О',L'У',L'Ы',L'Э',L'Ю',L'Я'};
            for(int i = 0;i<inquery;i++){
                for(int j = 0;j<=20;j++){
                    if(query[i]==alph[j]){
                        for(int z = 0;z<inquery-i;z++)
                            query[inquery+1-z] = query[(inquery-1)-z];
                            
                        query[i+1]=L'с';
                        query[i+2]=query[i];
                        inquery+=2;
                        i+=2;
                    }
                }
            }
            put(x,0,inquery,query);
            break;
        }
        case 4: //Каждая буква в слове заменяется на ее позицию в алфавите. Пример: кот ->121620, обработать только буквы.
        {
            x[25]=-1;
            for(int i = 0;i<inquery;i++){
            if (query[i] >= L'а' && query[i] <= L'я'){      
                    x[25] = (query[i] - L'а') + 1;
                    if(query[i]>=alphabet[8])x[25]++;}
                else if (query[i] == L'ё')            
                    x[25] = 7;         
                else if (query[i] >= L'А' && query[i] <= L'Я'){
                    x[25] = (query[i] - L'А') + 1;
                    if(query[i]>=alphabet[41])x[25]++;}
                else if (query[i] == L'Ё')                 
                    x[25] = 7;
            if(x[25]!=-1){printf("%d",x[25]);x[25]=-1;}
            }
            put(x,40,40,query);
            break;
        }
        case 5: //Заменяет буквы верхнего регистра на буквы нижнего и наоборот. Пример: Привет -> пРИВЕТ.
        {
            for(int i = 0;i<inquery;i++){
                for(int j = 0;j<=33*2;j++){
                    if(query[i]==alphabet[j]&&j<33){
                        query[i]=alphabet[j+33];
                    }
                    else if(query[i]==alphabet[j]&&j>32){
                        query[i]=alphabet[i-33];
                       
                    }
                }
            }
            put(x,0,inquery,query);
            break;
        }
        /*case 6: //Заменяет буквы на их двоичное представление из таблицы ASCII.Пример: кот ->101010101010111011100010
        {
            break;
        }*/
        case 7: /*Заменяет букву на заданное смещение в пределах алфавита (шифр
                  Цезаря), смещение задаётся параметром и может быть положительным или
                  отрицательным. Пример: кот 3 -> нсх, кот -3 -> злп*/
        {
            while(f[3][x[35]]>=L'0'&&f[3][x[35]]<=L'9'){
                x[34] = (x[34]*10)+(f[3][x[35]]-L'0');
                x[35]++;
            }
            for(int i = 0;i<inquery;i++){
                for(int j = 0;j<=33;j++){
                    if(query[i]==alphabet[j]&&j<33){
                        while(x[34]>33)x[34]-=33;
                        if(j+x[34]>=33)x[34]-=33;
                        query[i]=alphabet[j+x[34]];
                    }

                    else if(query[i]==alphabet[j]&&j>32){
                        while(x[34]>33)x[34]-=33;
                        if(j+x[34]>=66)x[34]-=33;
                        query[i]=alphabet[j+33+x[34]];
                    }
                }
            }
            put(x,0,inquery,query);
            break;
        }
        case 8: //Делит слово на два и оставляет большую часть. Пример: жук -> к, солнце -> сол
        {
            if(inquery%2!=0)x[34]=1;
            else x[34]=0;
            for (int i = 0; i<(inquery/2)+x[34];i++)
                x[35] +=query[i];
            for (int i = (inquery/2)+x[34]; i<inquery;i++)
                x[36] +=query[i];
            if(x[35]>x[36])
                put(x,0,(inquery/2)+x[34],query);
            else 
                put(x,(inquery/2)+x[34],inquery,query);
            break;
        }
        case 9: //Делит слово на два и оставляет меньшую часть. Пример: жук -> жу, солнце -> нце
        {
            if(inquery%2!=0)x[34]=1;
            else x[34]=0;
            for (int i = 0; i<(inquery/2)+x[34];i++)
                x[35] +=query[i];
            for (int i = (inquery/2)+x[34]; i<inquery;i++)
                x[36] +=query[i];
            if(x[35]<x[36])
                put(x,0,(inquery/2)+x[34],query);
            else 
                put(x,(inquery/2)+x[34],inquery,query);

            break;
        }
        case 10://Превращает русский текст в транслит русского текста. Пример кот ->kot, жук -> zhuk
        { 
            int translit[43]={
                L'a',L'b',L'v',L'g',L'd',L'e' , L'y',/**/L'o' , L'z',/**/L'h' , L'z',L'i',L'y',L'k',L'l',L'm',L'n',L'o',
                L'p',L'r',L's',L't',L'u',L'f',L'h',L'c' , L'c',/**/L'h' , L's',/**/L'h' , L's',/**/L'h',/**/L'c',/**/L'h',
                L'\'',L'y',L'\'',L'e',L'e' , L'y',/**/L'u' , L'y',/**/L'a'};

            for(int i =0;i>inquery;i++){
                if(
                    (query[i]  >= alphabet[0]     && query[i]  <= alphabet[5])      ||
                    (query[i]  >= alphabet[8]     && query[i]  <= alphabet[23])     ||
                    (query[i]  >= alphabet[27]    && query[i]  <= alphabet[30])     ||
                    (query[i]  >= alphabet[0+33]  && query[i]  <= alphabet[5+33])   ||
                    (query[i]  >= alphabet[8+33]  && query[i]  <= alphabet[23+33])  ||
                    (query[i]  >= alphabet[27+33] && query[i]  <= alphabet[30+33]))
                {
                    query[i]=translit[i];
                }
                else if (query[i] != alphabet[26] || query[i] != alphabet[26+33])
                {
                    for(int z = 0;z<inquery-i;z++)
                        query[inquery-z] = query[(inquery-1)-z];
                    query[i]=translit[i];
                    query[i+1]=translit[i+1];
                    inquery++;i++;
                }
                else
                {
                    for(int z = 0;z<inquery-i;z++)
                        query[inquery-z] = query[(inquery-1)-z];
                    for(int g =0;g<5;g++)
                        query[i+g] = translit[i+g];
                    inquery+=4;i+=4;
                }
            }
            put(x,0,inquery,query);
            break;
        }
    }
}


int last(int inquery,int *query){
     if((query[inquery-1]==L'.') ||
        (query[inquery-1]==L',') ||
        (query[inquery-1]==L'!') ||
        (query[inquery-1]==L'?')) {
        return 1;
        }
    return 0;
}


void put(int *x,int i,int inquery,int *query){

    if(i<inquery)
        for(;i<inquery;i++)
            printf("%lc",query[i]);

    if(i>inquery)
        for(;i>inquery;i--)
            printf("%lc",query[i]);

    if(x[30]!=x[2]){putwchar(L'\n');}
    if(x[31]!=x[3]){putwchar(L'\t');}
    if(x[33]!=x[4]){putwchar(L' ');}
    x[30]=x[2];
    x[31]=x[3];
    x[33]=x[4];
}


void printcount(int *x){
    int sum = 0;
    printf("\nStatistic");
    printf("\n\t \"Symb\" - [ammount]\n");
    printf("\n\t \"Letters\" - [%d]",x[0]);
    printf("\n\t \"Digits\" - [%d]",x[1]);
    printf("\n\t \"\\n\" - [%d]",x[2]);
    printf("\n\t \"\\t\" - [%d]",x[3]);
    printf("\n\t \"space\" - [%d]",x[4]);

    for (int i = 33; i <= 47; i++) {
        if (x[i-28] > 10)
            printf("\n\t \"%c\" - [%d]", i, x[i-28]);
        else
            sum+=x[i-28];
    }

    for (int i = 58; i <= 64; i++) {
        if(x[i-38]>10)
            printf("\n\t \"%c\" = [%d]", i, x[i-32]);
        else
            sum+=x[i-38];
    }

    printf("\n\t other - [%d]",sum+x[33]);
}


int str(char *a, char *b) {
    int i = 0;
    while(a[i] != L'\0' && b[i] != L'\0') {
        if(a[i] != b[i]) return 0;
        i++;
    }
    return a[i] == b[i];
}


int strquery(char *a, int *b){

    return 0;
}


int funcReturn(char *f){
    int swt=0;
    if(str(f,"1"))swt=1;
    if(str(f,"2"))swt=2;
    if(str(f,"3"))swt=3;
    if(str(f,"4"))swt=4;
    if(str(f,"5"))swt=5;
    if(str(f,"6"))swt=6;
    if(str(f,"7"))swt=7;
    if(str(f,"8"))swt=8;
    if(str(f,"9"))swt=9;
    if(str(f,"10"))swt=10;
    return swt;
}
