#include <ads/adscpp.h>

#include <ads/ddeinc.h>

#include <ads/adsinc.h>

#include <afc/cybernet.h>

#include <ads/Lists.h>

#include <ads/ListIter.h>

#include "pline.h"

#include "block.h"


#define DDE


static char *CybName= "2037551666__HMI_KYCAD";

const double max_distance = 0.5; // 0.5 metra za simbol


class WaterWay : public ADS_APP
{
public:
  WaterWay(int argc, char **argv);

private:
  BASIC_CPP_STUFF(WaterWay);
};




DDE_CLIENT_CONNECTION *chnl;

void PanTo(struct resbuf *)
{
  struct resbuf *rb;
  char handle[17];
  rb = ads_getargs();

  if (rb == NULL)
    {
      ads_printf("manjka argument handle\n");
      return;
    }

  ads_printf("rrestype = %d, resval %s\n", rb->restype, rb->resval.rstring);

  strcpy(handle, rb->resval.rstring);
  ads_relrb(rb);

  ads_name entres;
  int status = ads_handent(handle, entres);
  if (status != RTNORM)
    {
      ads_printf("Gradnik ne obstaja\n");
      return;
    }
vertex:
  rb = ads_entget(entres);
  assert(rb != NULL);
  struct resbuf *pos;
  for(pos = rb; pos != NULL; pos = pos->rbnext)
    {
      if (pos->restype == 0)
        {
          if ((strcmp(pos->resval.rstring, "LWPOLYLINE") == 0)
             || (strcmp(pos->resval.rstring, "POLYLINE") == 0))
            {
              // premakni se na prvi vertex

              ads_name head;
              ads_relrb(rb);
              head[0] = entres[0];
              head[1] = entres[1];
              status = ads_entnext(head, entres);
              assert( status == RTNORM);
              goto vertex;
            }
        }
      else if (pos->restype == 10)
        {
          ads_printf("Premik na %lf, %lf\n", pos->resval.rpoint[0], pos->resval.rpoint[1]);
          ads_command(RTSTR, "ZOOM", RTSTR, "C", RTPOINT, pos->resval.rpoint, RTSTR, "",  NULL);
          break;
        }
    }
  assert(pos != NULL);
  ads_relrb(rb);
}


void InsertPline(struct resbuf *)
{
  int status;
  static int plineCounter = 0;

  ads_name ss, ssInsert;
  struct resbuf *rb;
  long ssLength, ssInsertLength;

  rb = ads_buildlist (RTDXF0, "POLYLINE",  NULL);

  assert(rb != NULL);

  status = ads_ssget (NULL, NULL, NULL, rb, ss);

  ads_relrb (rb);


  if (status != RTNORM)         /* Prazen izbor */
    {
      ads_printf("Izbira preklicana\n");
      return;
    }


  rb = ads_buildlist(RTDXF0, "INSERT", NULL);


  status = ads_ssget("X", NULL, NULL,  rb, ssInsert);
  if (status != RTNORM)
    {
      ads_printf("Ni blokov v risbi\nIzbira ni mozna!");
      ads_relrb(rb);
      return;
    }


  Lists<cblock> blocks;

  status = ads_sslength (ssInsert, &ssInsertLength);
//  ads_printf("Total blocks %ld\n", ssInsertLength);

  for (long j = 0; j < ssInsertLength; j++)
    {
      ads_name name;
      struct resbuf *block_rb;
      ads_ssname(ssInsert, j, name);
      block_rb = ads_entget(name);
      blocks.append(cblock(block(block_rb)));
      ads_relrb(block_rb); 
    }
  status = ads_sslength (ss, &ssLength);
  ads_printf("Total blocks %ld\n", ssLength);

  struct resbuf *temp_rb;


  for (long i = 0; i < ssLength; ++i) // za vse PLINE

    {
      ads_name name;
      vec3 first, last;
      int firstExist, lastExist;
      pline *p;
      ads_ssname(ss, i, name);
      temp_rb = ads_entget(name);
      p = new pline(temp_rb);
      ADS_STRING msg;
      msg = "ODS," + p->handle();
      chnl->BeginSend();
      chnl->SendString(msg);
      chnl->EndSend();

#if 1

      first = p->first(); firstExist = 0; // ali je zacetni vozel na PLINE

      last = p->last();   lastExist = 0;  // ali je koncni vozel na PLINE

#endif


      ListIterators<cblock> iterator(blocks);
      for (iterator.reset(); !iterator.isDone(); iterator.next()) // za vse bloke

        {
          double distance;
//          ads_printf("item: [%lf %lf]\n",

//                     iterator.currentItem()->origin()[X],

//                     iterator.currentItem()->origin()[Y]);

          distance = p->nearest(iterator.currentItem()->origin());
          if (distance < max_distance)
            {
            ads_printf("Handle= %s, name = %s\n", 
                       iterator.currentItem()->handle().CString(),
                       iterator.currentItem()->name().CString(), 
                       distance);
            msg =   iterator.currentItem()->name() + ","
                           + iterator.currentItem()->handle();
            chnl->BeginSend();
            chnl->SendString(msg);
            chnl->EndSend();

            }
#if 1

          if ((iterator.currentItem()->origin() - first).length() < max_distance)
              firstExist++;
          if ((iterator.currentItem()->origin() - last).length() < max_distance)
              lastExist++;
#endif

        }
      if (!firstExist)   // dodaj nov  zacetni vozel in ga poslji

        {
          ads_point origin;
          ads_name  result;
          origin[0] = first[0];
          origin[1] = first[1];
          origin[2] = first[2];
          ads_printf("Nov blok na zacetku: [%lf %lf]\n",
                     origin[X],
                     origin[Y]);
          ads_command(RTSTR, "INSERT",  RTSTR, "KV", RTPOINT, origin, RTSTR, "17", 
                      RTSTR, "17", RTSTR, "0", NULL);
          ads_entlast(result);
          struct resbuf *block_rb = ads_entget(result);
          block newblock(block_rb);
          blocks.append(cblock(newblock));
          msg =   newblock.name() + "," + newblock.handle();
          chnl->BeginSend();
          chnl->SendString(msg);
          chnl->EndSend();
          ads_relrb(block_rb);
        }
      if (!lastExist)   // dodaj nov  KONCNI vozel in ga poslji

        {
          ads_point origin;
          ads_name  result;
          origin[0] = last[0];
          origin[1] = last[1];
          origin[2] = last[2];
          ads_printf("Nov blok na koncu: [%lf %lf]\n",
                     origin[X],
                     origin[Y]);
          ads_command(RTSTR, "INSERT",  RTSTR, "KV", RTPOINT, origin, RTSTR, "17", 
                      RTSTR, "17", RTSTR, "0", NULL);
          ads_entlast(result);
          struct resbuf *block_rb = ads_entget(result);
          block newblock(block_rb);
          blocks.append(cblock(newblock));
          msg =   newblock.name() + "," + newblock.handle();
          chnl->BeginSend();
          chnl->SendString(msg);
          chnl->EndSend();
          ads_relrb(block_rb);
        }
      char txtbuf[18];
      sprintf(txtbuf, "%d", ++plineCounter);
      p->Mark(txtbuf, "OZNAKE", 5);
      delete p;
      ads_relrb(temp_rb);
    }
}




void InsertContainer(struct resbuf *)
{
  int status;
  static int plineCounter = 0;

  ads_name ss;
  struct resbuf *rb;
  long ssLength;

  rb = ads_buildlist (RTDXF0, "INSERT",  NULL);

  assert(rb != NULL);

  status = ads_ssget (NULL, NULL, NULL, rb, ss);

  ads_relrb (rb);


  if (status != RTNORM)         /* Prazen izbor */
    {
      ads_printf("Izbira preklicana\n");
      return;
    }


  Lists<cblock> blocks;

  status = ads_sslength (ss, &ssLength);

//  ads_printf("Total blocks %ld\n", ssInsertLength);

  for (long j = 0; j < ssLength; j++)
    {
      ads_name name;
      struct resbuf *block_rb;
      ads_ssname(ss, j, name);
      block_rb = ads_entget(name);
      blocks.append(cblock(block(block_rb)));
      ads_relrb(block_rb); 
    }

  ads_printf("Total blocks %ld\n", ssLength);

  struct resbuf *temp_rb;

  ListIterators<cblock> iterator(blocks);
  for (iterator.reset(); !iterator.isDone(); iterator.next()) // za vse bloke

    {
        ADS_STRING msg;
//      ads_printf("item: [%lf %lf]\n",

//                 iterator.currentItem()->origin()[X],

//                 iterator.currentItem()->origin()[Y]);

        ads_printf("Handle= %s, name = %s\n", 
                   iterator.currentItem()->handle().CString(),
                   iterator.currentItem()->name().CString());
        msg =   "+" + iterator.currentItem()->name() + ","
                       + iterator.currentItem()->handle();
        chnl->BeginSend();
        chnl->SendString(msg);
        chnl->EndSend();

    }
}




void FindObject(struct resbuf *)
{
  int status;
  ads_name  ename;
  ads_point ptres;

  status = ads_entsel("Izberi gradnik>", ename, ptres);
  if (status != RTNORM)
    {
      ads_printf("Prekinjeno\n");
      return;
    }
  struct resbuf *rb, *rb_temp;

  ADS_STRING handle, oznaka, msg;
  rb = ads_entget(ename);
  assert (rb != NULL);
  for (rb_temp = rb;  rb_temp != NULL; rb_temp = rb_temp->rbnext)
    {
      switch (rb_temp->restype)
        {
          case 5:
            handle = ADS_STRING(rb_temp->resval.rstring);
            break;
          case 0:
            oznaka = ADS_STRING(rb_temp->resval.rstring);
            break;
        }
    }

 msg =  "_" + oznaka + "," + handle;
 chnl->BeginSend();
 chnl->SendString(msg);
 chnl->EndSend();
 ads_relrb(rb);

}




WaterWay::WaterWay(int argc, char **argv) : ADS_APP(argc, argv)
{
   InsertExternFunc(ADS_FUNC_INFO( ADS_FUNC( PanTo ),
                                  ADS_VOID_FUNC,  "pantohandle"));
   InsertExternFunc(ADS_FUNC_INFO( ADS_FUNC( InsertPline ), 
                                  ADS_VOID_FUNC,  "c:ip" ));
   InsertExternFunc(ADS_FUNC_INFO( ADS_FUNC( InsertContainer ), 
                                  ADS_VOID_FUNC,  "c:ic" ));
   InsertExternFunc(ADS_FUNC_INFO( ADS_FUNC( FindObject ), 
                                  ADS_VOID_FUNC,  "c:fo" ));
}


void main (int argc, char *argv[])
{
  WaterWay *app = new WaterWay(argc, argv);
#if 0

  chnl =  new DDE_CLIENT_CONNECTION(SERVER_INFO("c:/tmp", UNKNOWNSERVER));

  if (chnl->Init(ADS_STRING("WaterWay"), ADS_STRING("System"), 
            ADS_STRING("HANDLE")) != TRUE)
    {
      ads_printf("Cannot initiate channel\n");
      return;
    }
    
  if (chnl->SetupConnection())
    {
      ads_printf("DDE Connection OK\n");
    }
#endif

  app->Run();
#if 0

  delete chnl;
#endif

}



syntax highlighted by Code2HTML, v. 0.9.1