/**
 * Copyright (c) 2021 Dominic Masters
 * 
 * This software is released under the MIT License.
 * https://opensource.org/licenses/MIT
 */

#include "display.h"

scripterreturn_t _scriptPrimitiveCreate(scriptercontext_t *ctx) {
  primitive_t *primitive = malloc(sizeof(primitive_t));
  duk_push_pointer(ctx, primitive);
  return 1;
}

scripterreturn_t _scriptPrimitiveInit(scriptercontext_t *ctx) {
  primitive_t *primitive = duk_to_pointer(ctx, 0);
  int32_t verticeCount = duk_to_int32(ctx, 1);
  int32_t indiceCount = duk_to_int32(ctx, 2);
  primitiveInit(primitive, verticeCount, indiceCount);
  return 0;
}

scripterreturn_t _scriptPrimitiveDraw(scriptercontext_t *context) {
  primitive_t *primitive = duk_to_pointer(context, 0);
  int32_t start = duk_to_int32(context, 1);
  int32_t count = duk_to_int32(context, 2);
  primitiveDraw(primitive, start, count);
  return 0;
}

scripterreturn_t _scriptPrimitiveDispose(scriptercontext_t *context) {
  primitive_t *primitive = duk_to_pointer(context, 0);
  primitiveDispose(primitive);
  free(primitive);
  return 0;
}


scripterreturn_t _scriptQuadInit(scriptercontext_t *ctx) {
  quadInit(duk_to_pointer(ctx, 0), (float)duk_to_number(ctx, 1),
    (float)duk_to_number(ctx, 2), (float)duk_to_number(ctx, 3),
    (float)duk_to_number(ctx, 4), (float)duk_to_number(ctx, 5),
    (float)duk_to_number(ctx, 6), (float)duk_to_number(ctx, 7),
    (float)duk_to_number(ctx, 8), (float)duk_to_number(ctx, 9)
  );
  return 0;
}


scripterreturn_t _scriptCameraCreate(scriptercontext_t *ctx) {
  camera_t *camera = malloc(sizeof(camera_t));
  duk_push_pointer(ctx, camera);
  return 1;
}

scripterreturn_t _scriptCameraLookAt(scriptercontext_t *ctx) {
  cameraLookAt(duk_to_pointer(ctx, 0), 
    (float)duk_to_number(ctx, 1),
    (float)duk_to_number(ctx, 2),
    (float)duk_to_number(ctx, 3),
    (float)duk_to_number(ctx, 4),
    (float)duk_to_number(ctx, 5),
    (float)duk_to_number(ctx, 6)
  );
  return 0;
}

scripterreturn_t _scriptCameraLook(scriptercontext_t *ctx) {
  cameraLook(
    duk_to_pointer(ctx, 0), 
    (float)duk_to_number(ctx, 1),
    (float)duk_to_number(ctx, 2),
    (float)duk_to_number(ctx, 3),
    (float)duk_to_number(ctx, 4),
    (float)duk_to_number(ctx, 5),
    (float)duk_to_number(ctx, 6)
  );
  return 0;
}

scripterreturn_t _scriptCameraPerspective(scriptercontext_t *ctx) {
  cameraPerspective(
    duk_to_pointer(ctx, 0), 
    (float)duk_to_number(ctx, 1),
    (float)duk_to_number(ctx, 2),
    (float)duk_to_number(ctx, 3),
    (float)duk_to_number(ctx, 4)
  );
  return 0;
}

scripterreturn_t _scriptCameraOrtho(scriptercontext_t *ctx) {
  cameraOrtho(
    duk_to_pointer(ctx, 0), 
    (float)duk_to_number(ctx, 1),
    (float)duk_to_number(ctx, 2),
    (float)duk_to_number(ctx, 3),
    (float)duk_to_number(ctx, 4),
    (float)duk_to_number(ctx, 5),
    (float)duk_to_number(ctx, 6)
  );
  return 0;
}

scripterreturn_t _scriptCameraDispose(scriptercontext_t *ctx) {
  camera_t *camera = duk_to_pointer(ctx, 0);
  free(camera);
  return 0;
}


scripterreturn_t _scriptShaderCreate(scriptercontext_t *ctx) {
  shader_t *shader = malloc(sizeof(shader_t));
  duk_push_pointer(ctx, shader);
  return 1;
}

scripterreturn_t _scriptShaderInit(scriptercontext_t *ctx) {
  shader_t *shader = duk_to_pointer(ctx, 0);
  char *vertex = duk_to_string(ctx, 1);
  char *frag = duk_to_string(ctx, 2);
  shaderInit(shader, vertex, frag);
  return 0;
}

scripterreturn_t _scriptShaderDispose(scriptercontext_t *ctx) {
  shader_t *shader = duk_to_pointer(ctx, 0);
  shaderDispose(shader);
  free(shader);
  return 0;
}

scripterreturn_t _scriptShaderUse(scriptercontext_t *ctx) {
  shaderUse(duk_to_pointer(ctx, 0));
  return 0;
}

scripterreturn_t _scriptShaderUseCamera(scriptercontext_t *ctx) {
  shaderUseCamera(duk_to_pointer(ctx, 0), duk_to_pointer(ctx, 1));
  return 0;
}

scripterreturn_t _scriptShaderUseTexture(scriptercontext_t *ctx) {
  shaderUseTexture(duk_to_pointer(ctx, 0), duk_to_pointer(ctx, 1));
  return 0;
}

scripterreturn_t _scriptShaderUsePosition(scriptercontext_t *ctx) {
  shaderUsePosition(
    duk_to_pointer(ctx, 0), 
    (float)duk_to_number(ctx, 1),
    (float)duk_to_number(ctx, 2),
    (float)duk_to_number(ctx, 3),
    (float)duk_to_number(ctx, 4),
    (float)duk_to_number(ctx, 5),
    (float)duk_to_number(ctx, 6)
  );
  return 0;
}

scripterreturn_t _scriptShaderUsePositionAndScale(scriptercontext_t *ctx) {
  shaderUsePositionAndScale(
    duk_to_pointer(ctx, 0), 
    (float)duk_to_number(ctx, 1),
    (float)duk_to_number(ctx, 2),
    (float)duk_to_number(ctx, 3),

    (float)duk_to_number(ctx, 4),
    (float)duk_to_number(ctx, 5),
    (float)duk_to_number(ctx, 6),

    (float)duk_to_number(ctx, 7),
    (float)duk_to_number(ctx, 8),
    (float)duk_to_number(ctx, 9)
  );
  return 0;
}


scripterreturn_t _scriptTextureCreate(scriptercontext_t *ctx) {
  texture_t *texture = malloc(sizeof(texture_t));
  duk_push_pointer(ctx, texture);
  return 1;
}

scripterreturn_t _scriptTextureDispose(scriptercontext_t *ctx) {
  texture_t *texture = duk_to_pointer(ctx, 0);
  textureDispose(texture);
  free(texture);
  return 0;
}


void scriptsApiDisplay(scripter_t *s) {
  scripterDefineMethod(s, "primitiveCreate", 0, &_scriptPrimitiveCreate);
  scripterDefineMethod(s, "primitiveInit", 3, &_scriptPrimitiveInit);
  scripterDefineMethod(s, "primitiveDraw", 3, &_scriptPrimitiveDraw);
  scripterDefineMethod(s, "primitiveDispose",1,&_scriptPrimitiveDispose);

  scripterDefineMethod(s, "quadInit", 10, &_scriptQuadInit);

  scripterDefineMethod(s, "cameraCreate", 0, &_scriptCameraCreate);
  scripterDefineMethod(s, "cameraLookAt", 7, &_scriptCameraLookAt);
  scripterDefineMethod(s, "cameraLook", 7, &_scriptCameraLook);
  scripterDefineMethod(s, "cameraPerspective", 5, &_scriptCameraPerspective);
  scripterDefineMethod(s, "cameraOrtho", 7, &_scriptCameraOrtho);
  scripterDefineMethod(s, "cameraDispose", 1, &_scriptCameraDispose);

  scripterDefineMethod(s, "shaderCreate", 0, &_scriptShaderCreate); 
  scripterDefineMethod(s, "shaderInit", 3, &_scriptShaderInit);
  scripterDefineMethod(s, "shaderDispose", 1, &_scriptShaderDispose);
  scripterDefineMethod(s, "shaderUse", 1, &_scriptShaderUse);
  scripterDefineMethod(s, "shaderUseTexture", 2, &_scriptShaderUseTexture);
  scripterDefineMethod(s, "shaderUseCamera", 2, &_scriptShaderUseCamera);
  scripterDefineMethod(s, "shaderUsePosition", 7, &_scriptShaderUsePosition);
  scripterDefineMethod(
    s, "shaderUsePositionAndScale", 10, &_scriptShaderUsePositionAndScale
  );

  scripterDefineMethod(s, "textureCreate", 0, &_scriptTextureCreate);
  scripterDefineMethod(s, "textureDispose", 1, &_scriptTextureDispose);
}