#ifndef LANGUAGE_H
#define LANGUAGE_H

#include "arena.h"

#include <stdbool.h>
#include <stddef.h>

typedef enum {
  TYPE_VIDEO,
  TYPE_AUDIO,
  TYPE_COMBINED,
  TYPE_SUBTITLES,
  TYPE_INDEX,
  TYPE_DURATION,
  TYPE_SCALAR,
  TYPE_BOOL,
} ValueType;

typedef enum {
  SRC_VIDEO,
  SRC_AUDIO,
  SRC_COMBINED,
  SRC_SUBTITLES,
} SourceKind;

typedef enum {
  OP_DUP,
  OP_DROP,
  OP_SWAP,
  OP_OVER,
  OP_ROT,
  OP_GET_VIDEO,
  OP_GET_AUDIO,
  OP_GET_SUBTITLES,
  OP_SPLIT,
  OP_VIDEO_AT,
  OP_AUDIO_AT,
  OP_SUBTITLES_AT,
  OP_TAKE_VIDEO,
  OP_TAKE_AUDIO,
  OP_TAKE_SUBTITLES,
  OP_DROP_VIDEO,
  OP_DROP_AUDIO,
  OP_DROP_SUBTITLES,
  OP_ADD_VIDEO,
  OP_ADD_AUDIO,
  OP_ADD_SUBTITLES,
  OP_REPLACE_VIDEO,
  OP_REPLACE_AUDIO,
  OP_REPLACE_SUBTITLES,
  OP_MOVE_VIDEO,
  OP_MOVE_AUDIO,
  OP_MOVE_SUBTITLES,
  OP_LENGTH,
  OP_SLICE,
  OP_TAKE,
  OP_CONCAT,
  OP_DELAY,
  OP_MUX,
  OP_ATTACH,
  OP_VOLUME,
  OP_MIX,
  OP_SILENCE,
  OP_SPEED,
  OP_FADE_IN,
  OP_FADE_OUT,
  OP_ADD,
  OP_SUB,
  OP_MUL,
  OP_DIV,
  OP_EQ,
  OP_NE,
  OP_LT,
  OP_LE,
  OP_GT,
  OP_GE,
  OP_AND,
  OP_OR,
  OP_NOT,
  OP_IF,
  OP_ELSE,
  OP_END,
  OP_BEGIN,
  OP_WHILE,
  OP_REPEAT,
  OP_COUNT,
} Operation;

typedef enum {
  INST_SOURCE,
  INST_DURATION,
  INST_SCALAR,
  INST_BOOL,
  INST_INDEX,
  INST_OPERATION,
} InstructionKind;

typedef struct {
  InstructionKind kind;
  int line;
  union {
    struct {
      SourceKind kind;
      const char* path;
    } source;
    double number;
    Operation op;
  } as;
} Instruction;

typedef struct {
  Arena arena;
  Instruction* items;
  size_t count;
  size_t capacity;
} Program;

typedef struct {
  int line;
  char message[256];
} Error;

const char* type_name(ValueType type);
const char* operation_name(Operation operation);

#endif