#include <stdio.h>
#include <math.h>
#include "stdafx.h"
#include "Spring.h"
#include "SpringCtl.h"
#include "SpringImpl.h"
#include "graph.h"


void DRAWING::SetBounds(RECT &tmp)
{
  rect = tmp;
}

DRAWING::DRAWING(double _xMin, double _yMin, double _xMax, double _yMax)
{
  xMin = _xMin;  yMin = _yMin;  xMax = _xMax;  yMax = _yMax;
}

int DRAWING::TransformX(double x)
{
  double w = rect.right - rect.left;  
  return (x - xMin) * w / (xMax - xMin) + rect.left;
}
int DRAWING::TransformY(double y)
{
  double h = rect.bottom - rect.top;  
  return h - (y - yMin) * h / (yMax - yMin) + rect.top;
}


void DRAWING::Draw(HDC hdc)
{
   HPEN foreground = CreatePen(PS_SOLID, 1, 0x009896a0);
   HPEN oldForeground = (HPEN)SelectObject(hdc, foreground);

   int x0, y0, x1, y1, x2, y2, xTmp, yTmp;

   MoveToEx(hdc, x1 = TransformX(xMin), y0 = TransformY(0.0), NULL);
   LineTo(hdc, x2 = TransformX(xMax), y0);
   MoveToEx(hdc, x0 = TransformX(0.0), y1 = TransformY(yMin), NULL);
   LineTo(hdc, x0, y2 = TransformY(yMax));

   DeleteObject(SelectObject(hdc, oldForeground));
   foreground = CreatePen(PS_SOLID, 1, 0x00c5ddc4);
   oldForeground = (HPEN)SelectObject(hdc, foreground);

   for (double x = xMin;  x <= xMax;  x += 1.0) {
      if (x == 0.0)
        continue;
      MoveToEx(hdc, xTmp = TransformX(x), y1, NULL);
      LineTo(hdc, xTmp, y2);  
   }
   for (double y = yMin;  y <= yMax;  y += 1.0) {
      if (y == 0.0)
        continue;
      MoveToEx(hdc, x1, yTmp = TransformY(y), NULL);
      LineTo(hdc, x2, yTmp);  
   }
   DeleteObject(SelectObject(hdc, oldForeground));

   NODE *node;
   for (node = graph->First();  node;  node = node->Next())
      DrawEdges(hdc, node);
   for (node = graph->First();  node;  node = node->Next())
      DrawNode(hdc, node);

 /*
   char buffer[100];
   sprintf(buffer, "i = %d, F = %f", graph->iteration, graph->ForceSum());
   TextOut(hdc, 5, 5, buffer, strlen(buffer)); 
*/
}      

void DRAWING::DrawNode(HDC hdc, NODE *node)
{
  int x = TransformX(node->Center().x), y = TransformY(node->Center().y);
  Chord(hdc, x - 5, y - 5, x + 5, y + 5, x, y, x, y);
  SetBkMode(hdc, TRANSPARENT);
  TextOut(hdc, x, y, node->Name(), strlen(node->Name())); 

  HPEN foreground = CreatePen(PS_DOT, 0, 0x00c7222b);
  HPEN  oldForeground = (HPEN)SelectObject(hdc, foreground);
  MoveToEx(hdc, x, y, NULL);
  LineTo(hdc, TransformX(node->LastImpulse().x + node->Center().x), 
              TransformY(node->LastImpulse().y + node->Center().y)); 
  DeleteObject(SelectObject(hdc, oldForeground));
  foreground = CreatePen(PS_SOLID, 2, 0x001102ee);
  oldForeground = (HPEN)SelectObject(hdc, foreground);
  MoveToEx(hdc, x, y, NULL);
  LineTo(hdc, TransformX(node->LastImpulse().x * node->Temperature() + node->Center().x), 
              TransformY(node->LastImpulse().y * node->Temperature() + node->Center().y)); 
  DeleteObject(SelectObject(hdc, oldForeground));

}
void DRAWING::DrawEdges(HDC hdc, NODE *node)
{
  int x = TransformX(node->Center().x), y = TransformY(node->Center().y);

  NODE *node2;
  
  for (int k = 0;  node2 = node->Voisin(k);  )
  {
    MoveToEx(hdc, x, y, NULL);
    LineTo(hdc, TransformX(node2->Center().x), TransformY(node2->Center().y));
  }
}

void DRAWING::NextStep()
{
  graph->MainIteration();
}



NODE *NODE::Voisin(int &k)
{
  if (k < n)
  { EDGE *edge = edges[k++];
    NODE *otherNode = edge->TargetNode();

    if (otherNode == this)
      otherNode = edge->SourceNode();

    return otherNode;
  }
  return NULL;
}



BRIDGE::BRIDGE(CSpringCtl *_control)
              : drawing(- _control->width/2.0, - _control->height/2.0, _control->width/2.0, _control->height/2.0), 
                control(_control)
{
   GRAPH *g = new GRAPH;
   
   NODE *n1 = new NODE("1", 1.0, 1.0);    NODE *n2 = new NODE("2", 1.0, 1.0);   
   NODE *n3 = new NODE("3", 1.0, 1.0);    NODE *n4 = new NODE("4", 1.0, 1.0);    
   NODE *n5 = new NODE("5", 1.0, 1.0);    NODE *n6 = new NODE("6", 1.0, 1.0);
   NODE *n7 = new NODE("7", 1.0, 1.0);    NODE *n8 = new NODE("8", 1.0, 1.0);

   NODE *nA = new NODE("a", 1.0, 1.0);    NODE *nB = new NODE("b", 1.0, 1.0);
   NODE *nC = new NODE("c", 1.0, 1.0);    NODE *nD = new NODE("d", 1.0, 1.0);
   NODE *nE = new NODE("e", 1.0, 1.0);    NODE *nF = new NODE("f", 1.0, 1.0);
   NODE *nG = new NODE("g", 1.0, 1.0);    NODE *nH = new NODE("h", 1.0, 1.0);

   NODE *nX = new NODE("X", 1.0, 1.0);    NODE *nY = new NODE("Y", 1.0, 1.0);    NODE *nZ = new NODE("Z", 1.0, 1.0);

   n1->Connect(*n2);
   n2->Connect(*n3);
   n2->Connect(*n4);
   n3->Connect(*n5);
   n4->Connect(*n6);
   n5->Connect(*n7);
   n6->Connect(*n7);
   n7->Connect(*n8);
   n4->Connect(*nA);
   nA->Connect(*nB);
   nA->Connect(*nE);
   nB->Connect(*nC);
   nC->Connect(*nD);
   nD->Connect(*nE);
   nE->Connect(*nF);
   nF->Connect(*nG);
   nF->Connect(*nH);
   nX->Connect(*nY);
   nX->Connect(*nZ);
   nX->Connect(*n1);
   nB->Connect(*nZ); 
   nY->Connect(*nZ);
// nY->Connect(*n4);
   
   *g += *n1;
   *g += *n2;
   *g += *n3;
   *g += *n4;
   *g += *n5;
   *g += *n6;
   *g += *n7;
   *g += *n8;
   *g += *nA;  *g += *nB;  *g += *nC;  *g += *nD;  *g += *nE;  *g += *nF;
   *g += *nG;  *g += *nH;
   *g += *nX;  *g += *nY;  *g += *nZ; 
   g->SetBaryCenter();

   g->MainIteration();
   drawing.SetGraph(g);

}

BRIDGE::~BRIDGE()
{
}


void BRIDGE::Draw(HDC hdc, RECT &rect)
{
  drawing.SetBounds(rect);
  drawing.Draw(hdc);  
}

void BRIDGE::NextStep()
{
  drawing.NextStep();
}


