/*
Diplomova prace : Palubni pocitac

user - api pro spravu uzivatelu

Atmega128A 10 MHz XTAL

Autor: Ondrej Lutera

2011/2012

*/
#include "user.h"

user_t activeUser;
uint8_t activeUserIndex=0;
user_t ee_users[MAX_USERS] EEMEM;


unsigned char userLogout(void)
{

    memset((void *)&activeUser,0,sizeof(user_t));

    return 1;   /* do budoucna */

}

inline id_t getActiveUid(void)
{

    return activeUser.uid;

}

inline id_t getUserGid(uint8_t index)
{

    if(index<MAX_USERS)
    {

        return eeprom_read_word(&ee_users[index].gid);

    }

    return 0;

}
id_t getUserUid(uint8_t index)
{

    if(index<MAX_USERS)
    {

        return eeprom_read_word(&ee_users[index].uid);

    }

    return 0;

}
inline id_t getActiveGid(void)
{

    return activeUser.gid;

}

char * getActiveUserName(void)
{

    return (char *)(activeUser.name);

}



unsigned char checkUserDataYearFolder(user_t * user, uint16_t year)
{

    char location[30];
    char dir[10];

    sprintf_P(location,PSTR("%s/%02x/%s/%04u"),USERS_FOLDER,user->uid,DATA_FOLDER,year);

    if(!findDir(location))      // vytvor adresar dle roku pokud neexistuje
    {

        sprintf_P(location,PSTR("%s/%02x/%s"),USERS_FOLDER,user->uid,DATA_FOLDER);
        sprintf_P(dir,PSTR("%04u"),year);

        createDir(location,dir);

        return 1;

    }

    return 0;

}

unsigned char checkUserDataMonthFolder(user_t * user,uint16_t year,uint8_t month)
{

    char location[30];
    char dir[10];

    sprintf_P(location,PSTR("%s/%02x/%s/%04u/%02u"),USERS_FOLDER,user->uid,DATA_FOLDER,year,month);

    if(!findDir(location))      // vytvor adresar dle mesice pokud neexistuje
    {

        sprintf_P(location,PSTR("%s/%02x/%s/%04u"),USERS_FOLDER,user->uid,DATA_FOLDER,year);
        sprintf_P(dir,PSTR("%02u"),month);
        createDir(location,dir);
        return 1;
    }

    return 0;
}

unsigned char checkActiveUserDataYearFolder(uint16_t year)
{


    return checkUserDataYearFolder(&activeUser,year);

}

unsigned char checkActiveUserDataMonthFolder(uint16_t year,uint8_t month)
{

    return checkUserDataMonthFolder(&activeUser,year,month);


}
unsigned char setActiveUser(ibutton_t * ibutton)
{

    if(ibutton==NULL) return 0;
#ifdef CAR_DEBUG
    char buf[80];
#endif
    user_t user;
    pcf_t tim;
    unsigned char i;
    unsigned char j;
    unsigned char compare;

    for(i=0; i<MAX_USERS; i++)
    {

        eeprom_read_block(&user,&(ee_users[i]),sizeof(user_t));

        compare = 0;

        for(j=0; j<SP_SIZE; j++)
        {


            compare|=user.iButton.romCode[j]^ibutton->romCode[j];
#ifdef CAR_DEBUG
            snprintf(buf,80,"user %u:: %02x : %02x  -- %u \n",i,user.iButton.romCode[j],ibutton->romCode[j],compare);

            uart_puts(buf);
#endif

        }

        if(compare == 0) break;



    }

    if(compare == 0 && i < MAX_USERS)
    {
        getTimePCF(&tim);
        getFromPCF(&tim);

        if(user.expTime.year && user.expTime.month && user.expTime.day)
        {

            if(tim.year > user.expTime.year) return EXP_USER;
            else if(tim.year == user.expTime.year)
            {

                if(tim.month > user.expTime.month)return EXP_USER;
                else if(tim.month == user.expTime.month)
                {

                    if(tim.day > user.expTime.day) return EXP_USER;
                    else if(tim.day == user.expTime.day)
                    {

                        if(tim.hour > user.expTime.hour) return EXP_USER;
                        else if(tim.hour == user.expTime.hour)
                        {

                            if(tim.min > user.expTime.min) return EXP_USER;
                            else if(tim.min == user.expTime.min)
                            {

                                if(tim.sec >= user.expTime.sec) return EXP_USER;

                            }

                        }

                    }

                }

            }
        }

        memcpy(&activeUser,&user,sizeof(user_t));
        getTimePCF(&activeUser.lastLogin);
        getFromPCF(&activeUser.lastLogin);
        eeprom_update_block(&activeUser.lastLogin,&ee_users[i].lastLogin,sizeof(pcf_t));
        checkUserDataYearFolder(&activeUser,activeUser.lastLogin.year);     // vyhledej slozku a pokud neexistuje tak vytvor
        checkUserDataMonthFolder(&activeUser,activeUser.lastLogin.year,activeUser.lastLogin.month);     // napodobne
        activeUserIndex = i;
        return LOGIN_OK;

    }

    return LOGIN_ERR;



}

unsigned char userLogin(void)
{

    if(ibuttonFind())
    {

        ibutton_t ibutton1;
        ibutton_t ibutton2;
        unsigned char i;
        unsigned char compare;
        unsigned char repeat = 100;
        unsigned char mul=0xff;

        do
        {

            ibuttonRead(&ibutton1);

            _delay_ms(100);

            ibuttonRead(&ibutton2);

            compare = 0;

            mul=0xff;

            for(i=0; i<SP_SIZE; i++)
            {
                compare|=ibutton1.romCode[i]^ibutton2.romCode[i];
                mul &=ibutton1.romCode[i];  /* pokud je chyba sbernice tak vraci same 0xff coz nechceme */

            }


        }
        while((compare||mul==0xff)&& --repeat );

        if(compare || mul==0xff) return LOGIN_ERR;

        compare = setActiveUser(&ibutton1) ;

        if( compare !=LOGIN_ERR ) return compare;
        else return NEW_USER;

    }

    return LOGIN_ERR;

}

uint8_t checkRoot(void)
{

    if(USER_INIT_SET!=eeprom_read_byte(&ee_users[0].init))
    {

        return 0;

    }
    else return 1;

}

uint8_t initUser(uint8_t index, user_t * user)
{

    if(index < MAX_USERS && user!=NULL)
    {

        eeprom_update_block(user,&ee_users[index],sizeof(user_t));
        if(index==activeUserIndex) memcpy(&activeUser,user,sizeof(user_t));

        return 1;
    }

    return 0;
}

void getUserName(uint8_t index,char * name)
{

    if(index<MAX_USERS)eeprom_read_block(name,&ee_users[index].name,sizeof(char)*NAME_LEN);

}

void getUser(uint8_t index,user_t * data)
{

    if(index<MAX_USERS)eeprom_read_block(data,&ee_users[index],sizeof(user_t));

}

uint8_t getUserInitSet(uint8_t index)
{

    if(index<MAX_USERS) return eeprom_read_byte(&ee_users[index].init);
    else return 0;

}

uint8_t useriButtonIsSet(ibutton_t* iButton)
{

    uint8_t compare1 = 0xff;
    uint8_t compare2 = 0;
    uint8_t i;
    if(iButton!=NULL)
    {

        for(i=0; i<SP_SIZE; i++)
        {

            compare1&=iButton->romCode[i];
            compare2|=iButton->romCode[i];
        }

    }

    if(compare1==0xff || compare2==0) return 0;
    else return 1;
}

void setUserIbutton(uint8_t index,ibutton_t * ib)
{

    if(ib!=NULL && index < MAX_USERS)
    {
        eeprom_update_block(ib,&(ee_users[index].iButton),sizeof(ibutton_t));
    }


}
void getUserIbutton(uint8_t index,ibutton_t * ib)
{

    if(ib!=NULL && index < MAX_USERS)
    {
        eeprom_read_block(ib,&ee_users[index].iButton,sizeof(ibutton_t));
    }

}

void clearUserIbutton(uint8_t index)
{

    ibutton_t ibut;

    if(index < MAX_USERS)
    {

        memset(&ibut,0xff,sizeof(ibutton_t));

        eeprom_update_block(&ibut,&(ee_users[index].iButton),sizeof(ibutton_t));


    }

}

void resetActiveUserTripData(void)
{
    getTimePCF(&activeUser.tripStart);
    getFromPCF(&activeUser.tripStart);
    activeUser.lastData.meas.TripTime = 0;
    activeUser.lastData.meas.TripImp =  0;

    activeUser.lastData.meas.TripInj = 0;
    activeUser.lastData.index++;


}
void resetScrData(scr_t * data)
{

    if(data!=NULL)
    {
        uint8_t i,j;
        uint8_t num=0;

        for(i=0; i<MAX_SCREENS; i++)
            for(j=0; j<MAX_ITEMS; j++)
            {
                data->scr[i][j]=num++;

                if(num>MAX_VAL)num=0;

            }

    }

}

void resetUserScrData(uint8_t index)
{

    scr_t data;

    if(index<MAX_USERS)
    {

        eeprom_read_block(&data,&ee_users[index].scrData,sizeof(scr_t));

        resetScrData(&data);

        eeprom_update_block(&data,&ee_users[index].scrData,sizeof(scr_t));

    }
}

scr_t * getActiveUserScrData(void)
{

    return &activeUser.scrData;

}

void setActiveUserScrData(uint8_t scr,uint8_t box,uint8_t val)
{

    if(scr<MAX_SCREENS && box < MAX_ITEMS && val <= MAX_VAL)
    {

        activeUser.scrData.scr[scr][box]=val;

    }

}

inline odat_t *getActiveUserOpto(void)
{

    return &(activeUser.opto);

}

inline pcf_t * getActiveExpTime(void)
{

    return &activeUser.expTime;
}

inline uint8_t * getActiveTrackDelay(void)
{
    return &activeUser.trackDelay;
}

void setActiveUserOpto(odat_t * opto)
{

    memcpy(&(activeUser.opto),opto,sizeof(odat_t));

    eeprom_update_block(&(activeUser),&(ee_users[activeUserIndex]),sizeof(user_t));

}

void saveActiveUser(void)
{

    eeprom_update_block(&activeUser,&ee_users[activeUserIndex],sizeof(user_t));

}

cm_t * getActiveUserMeas(void)
{
    return &activeUser.lastData.meas;
}

void storeActiveUserMeas(uint8_t state)
{
    char location[30];
    char file[10];
    uint8_t status;
//    uint8_t tripIndex;
    pcf_t time;
    /* tyto promenne ukladaji predesly cas tj adresarovou strukturu..
       za predpokladu, ze jizda stale probiha a pritom dojde ke zmene dne/mesice/roku, jsou tyto data dale ukladany do stareho souboru..
       tedy ziskani nove cesty je provedeno pouze za predpokladu pocatku nove jizdy */
    static uint16_t oldYear=0;
    static uint16_t oldMonth = 0;
    static uint16_t oldDay = 0;

    if(state==STATE_STARTED)
    {
        getTimePCF(&time);
        oldYear = time.year;
        oldMonth = time.month;
        oldDay = time.day;

    }
    else if(state==STATE_NEW_RUNNING)   /* pokud je novy start ovsem stare trati tak ukladej do stareho souboru pod stary index trati */
    {
        data_t data;

        snprintf_P(location,30,PSTR("%s/%02x/%s"),USERS_FOLDER,activeUser.uid,DATA_FOLDER);

        if(findMeas(location,&data,1))  /* najdi posledni data v poslednim souboru */
        {

            oldYear = data.storeTime.year;
            oldMonth = data.storeTime.month;
            oldDay = data.storeTime.day;

        }

    }

    snprintf_P(location,30,PSTR("%s/%02x/%s/%04u/%02u"),USERS_FOLDER,activeUser.uid,DATA_FOLDER,oldYear,oldMonth,oldDay);

    snprintf_P(file,10,PSTR("%02u.dat"),oldDay);

    struct fat_file_struct *fd = openFile(location,file,&status);

    if(status==OLD_FILE || status==NEW_FILE)
    {

        if(status==OLD_FILE)    /* pokud soubor jiz existoval, patrne obsahuje data, pak najdi posledni index trasy */
        {

            activeUser.lastData.index = getLastIndex(fd);
            /* pokud je predan stav startu pak inkrementuj jizdu na novy index */
            if(state==STATE_STARTED)activeUser.lastData.index++;

        }
        else activeUser.lastData.index=0;

        /* uloz data */
        storeMeas(&activeUser.lastData,fd);
#ifdef CAR_DEBUG
        uart_puts_P("storeMeas -> ");
        uart_puts(location);
        uart_puts_P("/");
        uart_puts(file);
        uart_puts_P("\n TrackIndex:");
        uart_putc(activeUser.lastData.index);
        uart_puts_P("\n state=");
        uart_putc(state);
#endif

    }
    fat_close_file(fd);



}

inline void clearActiveUserAvgMeas(void)
{
    cm_t * data = &activeUser.lastData.meas;

    data->AvgInj = 0;
    data->AvgImp = 0;
    data->ActTime = 0;
    data->AvgRpm = 0;


}
inline void clearActiveUserTripMeas(void)
{
    cm_t * data = &activeUser.lastData.meas;

    data->TripInj = 0;
    data->TripImp = 0;

}

void activeUserPollData(void)
{

    cm_t * data = &activeUser.lastData.meas;

    inj_t inj_imp = getTmpInjImp();

    odo_t imp = getTmpImp();
    rpm_t rpm = getTmpRpm();
    tm_t tim = getTmpTime();

    data->AvgInj+=inj_imp;


    data->AvgImp += imp;
    data->AvgRpm += rpm;
    data->ActTime += tim;

    data->TripInj += inj_imp;

    data->TripImp +=imp;
    data->TripRpm += rpm;
    data->TripTime += tim;

    data->TotInj += inj_imp;

    data->TotImp +=imp;
    data->TotRpm += rpm;
    data->TotTime += tim;

}

uint8_t geActiveUserIndex(void)
{

    return activeUserIndex;

}

inline uint8_t* getActiveSuspendMin(void)
{

    return &activeUser.suspendDelay;
}
