#include <Windows.h>
#include <stdio.h>
#include <time.h>
#include <math.h>

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);

HINSTANCE gInst;
LPSTR ClassName = "third";

int WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR what, INT nCmdShow)
{
 gInst = hInstance;
 HWND hWnd;
 MSG Message;
 WNDCLASSA WndClass = { 0 };
 //
 WndClass.lpszClassName = ClassName;
 WndClass.lpfnWndProc = WndProc;
 WndClass.hInstance = hInstance;
 WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
 //

 RegisterClassA(&WndClass);

 hWnd = CreateWindowA(ClassName, (LPSTR)"title", WS_OVERLAPPEDWINDOW, 100, 100, 500, 500, NULL, NULL, hInstance, NULL);

 ShowWindow(hWnd, nCmdShow);

 while(GetMessage(&Message, 0, 0, 0)) {
  TranslateMessage(&Message);
  DispatchMessage(&Message);
 }

 return 0;

}



#define half(n) floor(0.5+n)
#define K 1000.0
#define AU (149600000.0*K)
#define day 86400.0
#define month 2592000.0
#define G (6.67*pow(10.0, -11.0))
#define ID_TIMER  100
#define ID_SCB1  200
#define ID_SCB2  300
#define ID_BT1  400
#define ID_BT2  500
#define ID_CB1  600

typedef struct { double x; double y; } vector;

void DrawAxis();
void GetTraject (char filename[32], double radius, double velocity, double T_record, double t_limit, double dt);

HDC hdc;
FILE* fp;

char planetname [8][32] = {"mercury", "venus", "earth", "mars", "jupiter", "saturn", "uranus", "neptune"};
struct { char filename[8][32]; double radius [8]; double velocity [8]; double period [8]; double T_record [8]; double dt [8]; } table
 = { { "mercury.txt", "venus.txt", "earth.txt", "mars.txt", "jupiter.txt", "saturn.txt", "uranus.txt", "neptune"},
    { 0.39*AU, 0.7*AU, 1.0*AU, 1.52*AU, 5.2*AU, 9.54*AU, 19.19*AU, 30.0*AU },
    { 1.61*30.0*K, 1.17*30.0*K, 1.0*30.0*K, 0.80*30.0*K, 0.43*30.0*K, 0.32*30.0*K, 0.23*30.0*K, 0.18*30.0*K },
          { 88.0*day, 224.7*day, 365.3*day, 687.0*day, 4333.0*day, 10756.0*day, 30707.0*day, 60223*day },
          { month/5.0, month/3.0, month/3.0, month/2.0, month, month, month, month },
          { 100, 100, 100, 100, 100, 100, 100, 100 }
    };


LRESULT CALLBACK WndProc (HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{

 static PAINTSTRUCT ps;
 static char Print [64];
 HBRUSH mybrush, oldbrush;
 static HWND hSCB[2], hCB;
 static BOOL drawing = FALSE;
 static char sel_planet = -1;
 static int count = 0;

 static double timerate = 30.0;
 static double size = 2;
 static double scale;
 scale = 250.0/(size*AU);
 static vector position[8][500] = { 0 };
 
 switch(iMessage) {
 case WM_CREATE :
  hSCB[0] = CreateWindowA("scrollbar", NULL, WS_CHILD | WS_VISIBLE | SBS_HORZ,
   10, 10, 200, 20, hWnd, (HMENU)ID_SCB1, gInst, NULL);
  hSCB[1] = CreateWindowA("scrollbar", NULL, WS_CHILD | WS_VISIBLE | SBS_HORZ,
   10, 60, 200, 20, hWnd, (HMENU)ID_SCB2, gInst, NULL);
  CreateWindowA("button",(LPSTR)"start", WS_CHILD | WS_VISIBLE,
   220, 10, 40, 70, hWnd, (HMENU)ID_BT1, gInst, NULL);
  hCB = CreateWindowA("combobox", NULL, WS_CHILD | WS_VISIBLE | CBS_DROPDOWN,
   310, 420, 100, 200, hWnd, (HMENU)ID_CB1, gInst, NULL);
  CreateWindowA("button",(LPSTR)"get", WS_CHILD | WS_VISIBLE,
   420, 420, 50, 25, hWnd, (HMENU)ID_BT2, gInst, NULL);
  SetScrollRange(hSCB[0], SB_CTL, 1, 365, TRUE);
  SetScrollPos(hSCB[0], SB_CTL, 30, TRUE);
  SetScrollRange(hSCB[1], SB_CTL, 1, 50, TRUE);
  SetScrollPos(hSCB[1], SB_CTL, 2, TRUE);
  for(int i=0; i<8; i++)
   SendMessageA(hCB, CB_ADDSTRING, 0, (LPARAM)planetname[i]);
  return 0;
  
 case WM_PAINT :
  hdc = BeginPaint(hWnd, &ps);

  sprintf(Print, "%.0lf Day/s", timerate);
  TextOutA(hdc, 10, 35, (LPSTR)Print, strlen(Print));
  sprintf(Print, "%.0lf AU", size);
  TextOutA(hdc, 10, 85, (LPSTR)Print, strlen(Print));

  if(drawing==TRUE){
   for(int i=0; i<8; i++)
    SetPixel(hdc, half(position[i][count].x*scale + 250), half(-position[i][count].y*scale + 250), BLACKNESS);
   count ++;
   DrawAxis();
   EndPaint(hWnd, &ps);
  }
  return 0;

 case WM_TIMER :
  InvalidateRect(hWnd, NULL, FALSE);
  return 0;
 
 case WM_COMMAND :
  switch(LOWORD(wParam)){
  case ID_BT1 :
   for(int i=0; i<8; i++){
    fp = fopen(table.filename[i], "r");
    for(int j=0; !feof(fp); j++)
     fscanf(fp, "%lf %lf", &position[i][j].x, &position[i][j].y);
    fclose(fp);
   }
   drawing = TRUE;
   SetTimer(hWnd, ID_TIMER, (int)(30*1000.0/timerate), NULL);
   break;
  case ID_BT2 :
   sel_planet = SendMessage(hCB, CB_GETCURSEL, 0, 0);
   GetTraject(table.filename[sel_planet], table.radius[sel_planet], table.velocity[sel_planet],
     table.T_record[sel_planet], table.period[sel_planet], table.dt[sel_planet]);
   break;
  }
  return 0;

 case WM_HSCROLL :
  switch(LOWORD(wParam)){
  case SB_LINELEFT :
   if((HWND)lParam==hSCB[0])
    timerate -= 1;
   if((HWND)lParam==hSCB[1])
    size -= 1;
   break;
  case SB_LINERIGHT :
   if((HWND)lParam==hSCB[0])
    timerate += 1;
   if((HWND)lParam==hSCB[1])
    size += 1;
   break;
  case SB_PAGELEFT :
   if((HWND)lParam==hSCB[0])
    timerate -= 15;
   if((HWND)lParam==hSCB[1])
    size -= 5;
   break;
  case SB_PAGERIGHT :
   if((HWND)lParam==hSCB[0])
    timerate += 15;
   if((HWND)lParam==hSCB[1])
    size += 5;
   break;
  case SB_THUMBTRACK :
   if((HWND)lParam==hSCB[0])
    timerate = HIWORD(wParam);
   if((HWND)lParam==hSCB[1])
    size = HIWORD(wParam);
   break;
  }
  if((HWND)lParam==hSCB[0])
   SetScrollPos((HWND)lParam, SB_CTL, timerate, TRUE);
  if((HWND)lParam==hSCB[1])
   SetScrollPos((HWND)lParam, SB_CTL, size, TRUE);
  InvalidateRect(hWnd, NULL, TRUE);
  return 0;
  
 case WM_DESTROY :
  KillTimer(hWnd, ID_TIMER);
  PostQuitMessage(0);
  return 0;
 }


 return DefWindowProc(hWnd, iMessage, wParam, lParam);

}

void DrawAxis()
{

 MoveToEx(hdc, 100, 250, NULL);
 LineTo(hdc, 400, 250);

 MoveToEx(hdc, 250, 100, NULL);
 LineTo(hdc, 250, 400);

}

void GetTraject (char filename[32], double radius, double velocity, double T_record, double t_limit, double dt)
{

 double t_record = 0;
 double M = 2.0* pow(10.0, 30.0);

 vector position = { -radius, 0 };
 vector speed = { 0, velocity };
 vector accel;

 double r, a;


 fp = fopen(filename, "w");

 for(double t=0; t<t_limit; t+=dt){
  t_record += dt;

  r = sqrt( pow(position.x, 2.0) + pow(position.y, 2.0) );
  a = G*M / pow(r, 2.0);

  accel.x = -a*position.x/r;
  accel.y = -a*position.y/r;
  speed.x += accel.x* dt;
  speed.y += accel.y* dt;
  position.x += speed.x* dt;
  position.y += speed.y* dt;

  if(t_record > T_record){
   t_record = 0;
   fprintf(fp, "%.0lf %.0lf \n", position.x, position.y);
  }
 }

 fclose(fp);

}