#include "base/base_inc.h"
#include "os/os_inc.h"

#include "freetype/freetype.h"

#include <stdio.h>

#include "base/base_inc.c"
#include "base/base_big_functions.c"
#include "os/os_inc.c"

int
main(int argc, char **argv){
  // init
  os_main_init(argc, argv);
  
  // check args
  if (argc != 2){
    printf("usage: %s <ttf-file>\n", argv[0]);
    exit(1);
  }
  
  // setup arena
  ArenaTemp scratch = arena_get_scratch(0, 0);
  
  // load file
  char *in_file_name = argv[1];
  String8 data = os_file_read(scratch.arena, str8_cstring((U8*)in_file_name));
  if (data.size == 0){
    printf("failed to load %s\n", in_file_name);
    exit(1);
  }
  
  // setup arena
  Arena *arena = arena_alloc();
  
  // parse the font
  {
    // setup ft library
    FT_Library ft = {0};
    FT_Error ft_init_result = FT_Init_FreeType(&ft);
    
    // create a face object
    FT_Face face = {0};
    FT_Error ft_open_result = max_U32;
    if (ft_init_result == 0){
      FT_Open_Args args = {0};
      args.flags = FT_OPEN_MEMORY;
      args.memory_base = data.str;
      args.memory_size = data.size;
      ft_open_result = FT_Open_Face(ft, &args, 0, &face);
    }
    
    // comprehend all the characters
    U32 min_index = max_U32;
    U32 max_index = 0;
    if (ft_open_result == 0){
      FT_ULong char_code = 0;
      for (;;){
        FT_UInt glyph_index = 0;
        char_code = FT_Get_Next_Char(face, char_code, &glyph_index);
        if (char_code == 0){
          break;
        }
        printf("(%u, %u)\n", (U32)char_code, glyph_index);
        min_index = Min(min_index, glyph_index);
        max_index = Max(max_index, glyph_index);
      }
    }
    
    // set size
    FT_Error ft_set_size_result = max_U32;
    if (ft_open_result == 0){
      FT_F26Dot6 char_size = (20 << 6);
      U32 dpi = 72;
      ft_set_size_result = FT_Set_Char_Size(face, char_size, char_size, dpi, dpi);
    }
    
    // get line advance
    S32 ascender = 0;
    S32 descender = 0;
    U32 line_height = 0;
    if (ft_set_size_result == 0){
      FT_SizeRec *size = face->size;
      ascender = size->metrics.ascender >> 6;;
      descender = size->metrics.descender >> 6;;
      U32 specified_height = size->metrics.height >> 6;
      line_height = Max(ascender - descender, specified_height);
    }
    
    // render all the glyphs
    if (ft_set_size_result == 0){
      for (U64 i = min_index; i <= max_index; i += 1){
        U32 glyph_index = (U32)i;
        FT_Int32 flags = FT_LOAD_DEFAULT;
        FT_Error load_glyph_result = FT_Load_Glyph(face, glyph_index, flags);
        
        FT_Error render_glyph_result = max_U32;
        if (load_glyph_result == 0){
          render_glyph_result = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
        }
        
        if (render_glyph_result == 0){
          FT_GlyphSlotRec *glyph = face->glyph;
          FT_Bitmap *bitmap = &glyph->bitmap;
          U32 width = bitmap->width;
          U32 height = bitmap->rows;
          if (width > 0 && height > 0){
            // convert to 8-bit monochrome bitmap
            U8 *buf = 0;
            switch (bitmap->pixel_mode){
              case FT_PIXEL_MODE_GRAY:
              {
                if (bitmap->num_grays == 256){
                  buf = push_array(arena, U8, width*height);
                  S32 pitch = bitmap->pitch;
                  U8 *first_line = bitmap->buffer;
                  if (pitch < 0){
                    first_line = bitmap->buffer + -pitch*(height - 1);
                  }
                  U8 *in_line = first_line;
                  U8 *out_line = buf;
                  for (U32 y = 0; y < height; y += 1){
                    MemoryCopy(out_line, in_line, width);
                    in_line += pitch;
                    out_line += width;
                  }
                }
              }break;
            }
            
            // unhandled pixel mode
            if (buf == 0){
              //...
            }
          }
        }
      }
    }
    
    // finish using the library
    FT_Error ft_done_result = max_U32;
    if (ft_init_result == 0){
      ft_done_result = FT_Done_FreeType(ft);
    }
  }
}

//$ freetype //
