#include "qcommon.h"

#include "dk_gce_interface.h"
#include "dk_gce_spline.h"
#include "dk_gce_script.h"
#include "dk_gce_entities.h"
#include "dk_buffer.h"

void CCubicSpline::Load(FILE *file) {
    fread(&a, sizeof(float), 1, file);
    fread(&b, sizeof(float), 1, file);
    fread(&c, sizeof(float), 1, file);
    fread(&d, sizeof(float), 1, file);
}

void CPointSpline::Load(FILE *file) {
    x.Load(file);
    y.Load(file);
    z.Load(file);
}

void CSplineSequence::Load(FILE *file, int version) {
    //reset our shit.
    Reset();

    //load the number of points we have.
    fread(&num_points, sizeof(int), 1, file);

    //allocate our arrays.
    if (num_points > 1) {
        times = new float[num_points - 1];

        pos_splines = new CPointSpline *[num_points - 1];
        dir_splines = new CPointSpline *[num_points - 1];
    }

    if (num_points > 0) {
        points = new point[num_points];
        velocity_norm = new point[num_points];
        velocity = new float[num_points];

        directions = new point[num_points];
        dir_vel_norm = new point[num_points];
        dir_vel = new float[num_points];
    }

    //load the "stuff"
    for (int i = 0; i < num_points; i++) {
        fread(&points[i], sizeof(point), 1, file);
        fread(&velocity_norm[i], sizeof(point), 1, file);
        fread(&velocity[i], sizeof(float), 1, file);

        fread(&directions[i], sizeof(point), 1, file);
        fread(&dir_vel_norm[i], sizeof(point), 1, file);
        fread(&dir_vel[i], sizeof(float), 1, file);
    }

    for (i = 0; i < num_points - 1; i++) {
        fread(&times[i], sizeof(float), 1, file);

        pos_splines[i] = new CPointSpline();
        pos_splines[i]->Load(file);

        dir_splines[i] = new CPointSpline();
        dir_splines[i]->Load(file);
    }

    fread(&velocity_start, sizeof(end_vel), 1, file);
    fread(&velocity_end, sizeof(end_vel), 1, file);
    fread(&total_time, sizeof(float), 1, file);
}

void CCinematicScript::Load(FILE *file, int version, const char *name) {
    //clear out all of our data.
    Reset();

    shots.Load(file, version);

    //set our names.
    strncpy(this->name, name, 64);
    strncpy(disk_name, name, 64);
    this->name[63] = '\0';
    disk_name[63] = '\0';

    //check if we have camera info.
    CheckCameraInfo();
}

void CScriptShot::Load(FILE *file, int version) {
    Reset();

    //load the spline sequence.
    sequence->Load(file, version);

    //load camera target info.
    fread(&target_flag, sizeof(target_flag), 1, file);

    //load shot end info.
    fread(&end_flag, sizeof(end_flag), 1, file);
    fread(&extra_time_start, sizeof(extra_time_start), 1, file);
    fread(&extra_time_end, sizeof(extra_time_end), 1, file);

    if (version >= 1) {
        sounds.Load(file, version);
    }

    if (version >= 2) {
        entities.Load(file, version);
    }

    if (version >= 3) {
        entity_camera_target.Load(file, version);
        entity_shot_end.Load(file, version);
    }

//    end_flag = SE_ENTITY;
//    entity_shot_end = "m3";
}

const CCinematicScript *LoadScript(const char *name) {
    if (name == NULL || name[0] == '\0') return NULL;

    //make the file name.
    buffer128 filename("cin/scripts/%s.script", name);

    //open the file.
    FILE *file = NULL;
    FS_FOpenFile(filename, &file);
    if (file == NULL) return NULL;

    //read the version number out of the file.
    int version;
    fread(&version, sizeof(int), 1, file);

    //check the version number
    if (version > SCRIPT_FILE_VERSION) {
        //the version on disk is greater than we know how to read.
        FS_FCloseFile(file);
        return NULL;
    }

    //create a new script.
    CCinematicScript *script = new CCinematicScript();

    //load the script.
    script->Load(file, version, name);

    //close the file
    FS_FCloseFile(file);

    //return the script.
    return script;
}

void CScriptSound::Load(FILE *file, int version) {
    fread(&filename[0], sizeof(filename), 1, file);

    fread(&time, sizeof(time), 1, file);
}

void DeleteScript(const CCinematicScript *script) {
    if (script == NULL) return;

    delete (CCinematicScript *)script;
}

void CScriptEntity::Load(FILE *file, int version) {
    //load our name.
    if (version >= 3) {
        name.Load(file, version);
    }
    else {
        char name_str[16];
        fread(&name_str[0], sizeof(name_str), 1, file);

        name = name_str;
    }

    //load the tasks.
    tasks.Load(file, version);
}

void CScriptEntityTask::Load(FILE *file, int version) {
    //load the type.
    fread(&type, sizeof(type), 1, file);

    //load the time;
    fread(&time, sizeof(time), 1, file);

    //load the position and direction.
    fread(&destination, sizeof(destination), 1, file);
    fread(&direction, sizeof(direction), 1, file);
}

