//
//  array.c
//  Arrays which contain data number and pointer of object.
//  AI002
//
//  Created by 西田　耀 on 13/01/01.
//  Copyright (c) 2013年 Hikaru Nishida. All rights reserved.
//

#include "core.h"

AI_Array *AI_Array_Initialize(void)
{
    return NULL;
}

AI_Array *AI_Array_Allocate(void)
{
    AI_Array *tag;
    
    tag = (AI_Array *)malloc(sizeof(AI_Array));
    
    if(tag == NULL){
        AI_SpeakError("Allocation error.\n", NULL);
        exit(EXIT_FAILURE);
    }
    
    memset(tag, 0, sizeof(AI_Array));
    
    return tag;
}

void AI_Array_Free(AI_Array **start)
{
    //Array全体をFreeする。
    //内部ポインタの参照先については関知しない。
    AI_Array *now, *next;
    
    now = *start;
    *start = NULL;
    
    for(; now != NULL; ){
        next = now->next;
        free(now);
        now = next;
    }
    return;
}

void AI_Array_FreePointer(AI_Array *start)
{
    //Pointerの参照先をすべてFree.
    //Array自体はFreeしない。
    int i;
    
    for(; start != NULL; start = start->next){
        for(i = 0; i < start->using_tags; i++){
            if(start->tag[i].pointer != NULL){
                free(start->tag[i].pointer);
                start->tag[i].pointer = NULL;
            }
        }
        //free(now);
    }
    return;
}

uint AI_Array_GetDataIDByIndex(const AI_Array *start, int index)
{
    for(; (index / AI_ARRAY_PACKDATAS) > 0; index -= AI_ARRAY_PACKDATAS){
        if(start == NULL){
            return AI_DATAID_NULL;
        }
        start = start->next;
    }
    if(start == NULL){
        return AI_DATAID_NULL;
    }
    return start->tag[index].dataID;
}

void *AI_Array_GetPointerByIndex(const AI_Array *start, int index)
{
    for(; (index / AI_ARRAY_PACKDATAS) > 0; index -= AI_ARRAY_PACKDATAS){
        if(start == NULL){
            return NULL;
        }
        start = start->next;
    }
    if(start == NULL){
        return NULL;
    }
    return start->tag[index].pointer;
}

int AI_Array_GetIndexByDataID(const AI_Array *start, int dataID)
{
    int i, tags;
    
    tags = AI_Array_GetNumberOfTags(start);
    
    for(i = 0; i < tags; i++){
        if(AI_Array_GetDataIDByIndex(start, i) == dataID){
            return i;
        }
    }
    return AI_ARRAY_INDEX_NOTFOUND;
}

void *AI_Array_GetPointerByDataID(const AI_Array *start, int dataID)
{
    int i, tags;
    
    tags = AI_Array_GetNumberOfTags(start);
    
    for(i = 0; i < tags; i++){
        if(AI_Array_GetDataIDByIndex(start, i) == dataID){
            return AI_Array_GetPointerByIndex(start, i);
        }
    }
    return NULL;
}

int AI_Array_GetNumberOfTags(const AI_Array *start)
{
    int tags;
    
    tags = 0;
    
    for(; start != NULL; start = start->next){
        tags += start->using_tags;
    }
    return tags;
}

int AI_Array_AppendLast(AI_Array **start, uint dataID, void *pointer)
{
    int index;
    
    index = 0;
    for(; *start != NULL && (*start)->using_tags == AI_ARRAY_PACKDATAS; start = &((*start)->next)){
        index += AI_ARRAY_PACKDATAS;
    }
    
    if(*start == NULL){
        *start = AI_Array_Allocate();
    }
    (*start)->tag[(*start)->using_tags].dataID = dataID;
    (*start)->tag[(*start)->using_tags].pointer = pointer;
    (*start)->using_tags++;
    
    return index + (*start)->using_tags - 1;
}

AI_ArrayTag *AI_Array_GetTagPointerByIndex(AI_Array *start, int index)
{
    for(; (index / AI_ARRAY_PACKDATAS) > 0; index -= AI_ARRAY_PACKDATAS){
        if(start == NULL){
            return NULL;
        }
        start = start->next;
    }
    if(start == NULL){
        return NULL;
    }
    return &start->tag[index];
}
