/* ex11-2.c --- OpenGLならではの座標変換
 *
 * cc ex11-2.c -g -O2 -Wall -o ex11-2 -I/usr/include/freetype2 -lftgl -lglfw -lGLU -lGL -lX11 -lXrandr -lm
 */

#include <stdio.h>
#include <math.h>
#include <unistd.h>
#include <GL/glfw.h>
#include <FTGL/ftgl.h>

#define CROSSING_SIZE 100  /* 交差点数=100 */
#define MAX_NAME_SIZE  50  /* 最大文字数50文字(半角) */

/* 座標変換マクロの定義 */
#define ORIGIN_X      0.0
#define ORIGIN_Y      0.0
#define REAL_SIZE_X   8.0
#define REAL_SIZE_Y   8.0

#ifndef FONT_FILENAME
/* 演習サーバに用意されているフォントのファイル名 */
#define FONT_FILENAME "/usr/share/fonts/truetype/fonts-japanese-gothic.ttf"
#endif
static FTGLfont *font; /* 読み込んだフォントを差すポインタ */

/* データ構造の定義 */
typedef struct {
    double x, y;           /* 位置 x, y */
} Position;                /* 位置を表す構造体 */

typedef struct {
    int id;                /* 交差点番号 */
    Position pos;          /* 位置を表す構造体 */
    double wait;           /* 平均待ち時間 */
    char jname[MAX_NAME_SIZE];   /* 交差点名(日本語) */
    char ename[MAX_NAME_SIZE];   /* 交差点名(ローマ字) */
    int points;            /* 交差道路数 */
    int next[5];           /* 隣接する交差点番号 */
} Crossing;

/* データを格納する変数の定義 */
static Crossing cross[CROSSING_SIZE];

/* 円を描画 */
static void draw_circle(double x, double y, double r) {
    int const N = 12;             /* 円周を 12分割して線分で描画することにする */
    int i;

    glBegin(GL_LINE_LOOP);
    for (i = 0; i < N; i++)
        glVertex2d(x + cos(2 * M_PI * i / N) * r,
                   y + sin(2 * M_PI * i / N) * r);
    glEnd();
}

/* 文字列を描画 */
static void draw_outtextxy(double x, double y, char const *text) {
    double const scale = 0.01;
    glPushMatrix();
    glTranslated(x, y, 0.0);
    glScaled(scale, scale, scale);
    ftglRenderFont(font, text, FTGL_RENDER_ALL);
    glPopMatrix();
}

/* ファイルの読み込み */
static int map_read(char *filename) {
    FILE *fp;
    int i, j;
    int crossing_number;          /* 交差点数 */

    fp = fopen(filename, "r");
    if (fp == NULL) {
        perror(filename);
        return -1;
    }

    /* はじめに交差点数を読み込む */
    fscanf(fp, "%d", &crossing_number);

    for (i = 0; i < crossing_number; i++) {
        /* 関数fprintfを使って、構造体のデータを
             ファイルへ書き出すプログラムを記入しなさい */

        fscanf(fp, "%d,%lf,%lf,%lf,%[^,],%[^,],%d",
                     &(cross[i].id), &(cross[i].pos.x), &(cross[i].pos.y),
                     &(cross[i].wait), cross[i].jname,
                     cross[i].ename, &(cross[i].points));

        for (j = 0; j < cross[i].points; j++) {
            fscanf(fp, ",%d", &(cross[i].next[j]));
        }

    }
    fclose(fp);

    /* ファイルから読み込んだ交差点数を返す */
    return crossing_number;
}

/* 道路網の表示 (新しく作成する部分) */
static void map_show(int crossing_number) {
    int i, j;

    for (i = 0; i < crossing_number; i++) {     /* 交差点毎のループ */
        double x0 = cross[i].pos.x;
        double y0 = cross[i].pos.y;

        /* 交差点を表す円を描く */
        glColor3d(1.0, 0.5, 0.5);
        draw_circle(x0, y0, 0.1);

        /* 交差点の名前を描く */
        glColor3d(1.0, 1.0, 0.0);
        draw_outtextxy(x0, y0, cross[i].jname);

        /* 交差点から伸びる道路を描く */
        glColor3d(1.0, 1.0, 1.0);
        glBegin(GL_LINES);
        for (j = 0; j < cross[i].points; j++) {
            double x1 = cross[ cross[i].next[j] ].pos.x;
            double y1 = cross[ cross[i].next[j] ].pos.y;
            glVertex2d(x0, y0);
            glVertex2d(x1, y1);
        }
        glEnd();
    }
}

int main(void) {
    int crossing_number;          /* 交差点数 */

    /* グラフィック環境を初期化して、ウィンドウを開く */
    glfwInit();
    glfwOpenWindow(640, 640, 0, 0, 0, 0, 0, 0, GLFW_WINDOW);

    /* (ORIGIN_X, ORIGIN_Y) を中心に、REAL_SIZE_X * REAL_SIZE_Y の範囲の
    空間をビューポートに投影する */
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(ORIGIN_X + REAL_SIZE_X * -0.5, ORIGIN_X + REAL_SIZE_X * 0.5,
            ORIGIN_Y + REAL_SIZE_Y * -0.5, ORIGIN_Y + REAL_SIZE_Y * 0.5,
            -1.0, 1.0);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    /* 地図をx軸回りに45度回転。斜めからの表示になる。*/
    glRotatef(45.0, 1.0, 0.0, 0.0);
    /* 地図を時計回りに30度回転。z軸回りに回転させる。*/
    /* glRotatef(-30.0, 0.0, 0.0, 1.0); */
    /* 地図を2分の1に縮小 */
    glScalef(0.5, 0.5, 1.0);

    /* 文字列描画のためのフォントの読み込みと設定 */
    font = ftglCreateExtrudeFont(FONT_FILENAME);
    if (font == NULL) {
        perror(FONT_FILENAME);
        fprintf(stderr, "could not load font\n");
        exit(1);
    }
    ftglSetFontFaceSize(font, 24, 24);
    ftglSetFontDepth(font, 0.01);
    ftglSetFontOutset(font, 0, 0.1);
    ftglSetFontCharMap(font, ft_encoding_unicode);

    /* マップファイルの読み込み */
    crossing_number = map_read("map2.dat");
    if (crossing_number < 0) {
        fprintf(stderr, "couldn't read map file\n");
        exit(1);
    }

    while (1) {
        int width, height;

        /* Esc が押されるかウィンドウが閉じられたらおしまい */
        glfwWaitEvents();
        if (glfwGetKey(GLFW_KEY_ESC) || !glfwGetWindowParam(GLFW_OPENED))
            break;

        glfwGetWindowSize(&width, &height); /* 現在のウィンドウサイズを取得する */
        glViewport(0, 0, width, height); /* ウィンドウ全面をビューポートにする */

        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        glClear(GL_COLOR_BUFFER_BIT); /* バックバッファを黒で塗り潰す */

        map_show(crossing_number);                /* 道路網の表示 */
        glfwSwapBuffers(); /* フロントバッファとバックバッファを入れ替える */
    }

    glfwTerminate();

    return 0;
}