/*
  EIMILTextUtil.c
    EIMIL journaling system.
*/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>

#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_MEMORY_H
#include <memory.h>
#endif

#include <EIMIL.h>
#include "EIMILint.h"

#define EIMIL_JOURNAL_MAX_SLOT_SIZE 128
#define EIMIL_JOURNAL_CHECK(eh) ((((EIMIL_data*)eh)->pjst) ? 1 : EIMIL_journal_initialize(eh))

int
EIMIL_journal_initialize(
    EIMIL_handle eh
)
{
    int i;
    EIMIL_data *ped = (EIMIL_data*) eh;
    EIMIL_journal *pj, *pjh;
    pj = (EIMIL_journal*) malloc(sizeof(EIMIL_journal)
				 * EIMIL_JOURNAL_MAX_SLOT_SIZE);
    if (!pj) return 0;
    memset(pj, 0, sizeof(EIMIL_journal) * EIMIL_JOURNAL_MAX_SLOT_SIZE);
    ped->pjst = pjh = pj;
    for (i = 0;i < EIMIL_JOURNAL_MAX_SLOT_SIZE - 1;i++) {
	pj->next = &pj[1];
	pj[1].prev = pj;
	pj++;
    }
    pj->next = pjh;
    pjh->prev = pj;

    return 1;
}

void
EIMIL_journal_free(
    EIMIL_handle eh
)
{
    int i;
    EIMIL_data *ped = (EIMIL_data*) eh;
    EIMIL_journal *pj, *pjh;

    pjh = NULL;
    pj = ped->pjst;
    for (i = 0; i < EIMIL_JOURNAL_MAX_SLOT_SIZE; i++) {
        fprintf(stderr, "hoge\n");
        if (!pj) break;
	if (pj->pv) EIMIL_RMREF(*pj->pv);
	if ((pj->next - pj) < 0) pjh = pj->next;
	pj = pj->next;
    }

    if (pjh) free(pjh);
    /*
    ASSERT(pjh);
    free(pjh);
    */
}

int
EIMIL_journal_set_point(
    EIMIL_handle eh,
    EIMIL_TID *ptid
)
{
    int cid;
    EIMIL_journal *pcj;
    EIMIL_data *ped = (EIMIL_data*) eh;

    if (!EIMIL_JOURNAL_CHECK(eh)) return 0;
    pcj = ped->pjst->next;
    cid = ped->current_journal_id;
    cid++;
    pcj->id = cid;
    if (pcj->pv) {
	EIMIL_RMREF(*pcj->pv);
	pcj->pv = NULL;
    }
    if (ped->current_journal_id >= EIMIL_JOURNAL_ID_MAX) {
	ped->current_journal_id = 1;
    }else{
	ped->current_journal_id = cid;
    }

    return 0;
}

int
EIMIL_journal_record_change(
    EIMIL_handle eh,
    EIMIL_symbol *psym
)
{
    EIMIL_data *ped = (EIMIL_data*) eh;
    EIMIL_journal *pcj;

    ASSERT(psym->cat == EIMIL_CAT_VARIABLE);
    if (!EIMIL_JOURNAL_CHECK(eh)) return 0;
    pcj = ped->pjst;

    pcj->pv = EIMIL_copy_value(psym->obj.v.pv);
    EIMIL_ADDREF(*pcj->pv);
		
    if (EIMIL_JOURNAL_EMPTY_SLOT(*pcj)) {
	pcj->id = EIMIL_JOURNAL_NONRECORD_TID;
    }
    pcj = pcj->next;
    pcj->id = EIMIL_JOURNAL_EMPTY_TID;
    if (pcj->pv) {
	EIMIL_RMREF(*pcj->pv);
	pcj->pv = NULL;
    }
    ped->pjst = pcj;
    return 1;
}

int
EIMIL_journal_prev_val(
    EIMIL_handle eh,
    EIMIL_TID tid,
    EIMIL_symbol *psym,
    EIMIL_value **ppv
)
{
    int i;
    EIMIL_data *ped = (EIMIL_data*) eh;
    EIMIL_journal *pcj, *pj;

    ASSERT(psym->cat == EIMIL_CAT_VARIABLE);
    if (!ped->pjst) return 0;
    pcj = ped->pjst;
    pj = NULL;
    for (i = 0; i < EIMIL_JOURNAL_MAX_SLOT_SIZE; i++) {
	if (pcj->psym == psym) pj = pcj;
	if (pcj->id == tid) break;
	pcj = pcj->prev;
	ASSERT(pcj->pv);
    }
    if (!pj) return 0;
    *ppv = pj->pv;

    return 1;
}

int
EIMIL_journal_rollback(
    EIMIL_handle eh,
    EIMIL_TID tid
)
{
	/* TODO */
}



/* Local Variables: */
/* c-file-style: "iiim-project" */
/* End: */
