// Copyright (C) 1999-2015
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"

#include <tk.h>

#include "vect.h"
#include "fitsimage.h"

Vect::Vect(Base* p, const Vector& pt, double mag, double ang)
  : Line(p, pt, pt)
{
  strcpy(type_,"vector");
  p2 = Vector(mag,0) * Rotate(ang) * FlipY() * Translate(p1);
  updateBBox();
}

Vect::Vect(Base* p, const Vector& pt,
	   double mag, double ang,
	   int arr,
	   const char* clr, int* dsh,
	   int wth, const char* fnt, const char* txt, 
	   unsigned short prop, const char* cmt, 
	   const List<Tag>& tg, const List<CallBack>& cb) 
  : Line(p, pt, pt, 0, arr, clr, dsh, wth, fnt, txt, prop, cmt, tg, cb)
{
  strcpy(type_,"vector");
  p2 = Vector(mag,0) * Rotate(ang) * FlipY() * Translate(p1);
  updateBBox();
}

Vect::Vect(Base* p, const Vector& ptr1,
	   const Vector& ptr2,
	   int arr,
	   const char* clr, int* dsh,
	   int wth, const char* fnt, const char* txt, 
	   unsigned short prop, const char* cmt, 
	   const List<Tag>& tg, const List<CallBack>& cb) 
  : Line(p, ptr1, ptr2, 0, arr, clr, dsh, wth, fnt, txt, prop, cmt, tg, cb)
{
  strcpy(type_,"vector");
}

void Vect::setPoints(const Vector& pt, double mag, double ang)
{
  p1 = pt;
  p2 = Vector(mag,0) * Rotate(ang) * FlipY() * Translate(p1);
  updateBBox();

  doCallBack(CallBack::EDITCB);
}

// list

void Vect::list(ostream& str, Coord::CoordSystem sys, Coord::SkyFrame sky, 
		Coord::SkyFormat format, int conj, int strip)
{
  if (!strip) {
    FitsImage* ptr = parent->findFits(sys,center);
    listPre(str, sys, sky, ptr, strip, 1);

    switch (sys) {
    case Coord::IMAGE:
    case Coord::PHYSICAL:
    case Coord::DETECTOR:
    case Coord::AMPLIFIER:
      {
	Vector v1 = ptr->mapFromRef(p1,sys);
	double mag = (p2-p1).length();
	double ang = (p2-p1).angle();
	str << type_ << '(' << setprecision(8) << v1[0] << ',' << v1[1] << ','
	    << ptr->mapLenFromRef(mag,sys) << ',' 
	    << radToDeg(parent->mapAngleFromRef(ang,sys)) << ')';
      }
      break;
    default:
      if (ptr->hasWCS(sys)) {
	if (ptr->hasWCSCel(sys)) {
	  switch (format) {
	  case Coord::DEGREES:
	    {
	      Vector v1 = ptr->mapFromRef(p1,sys,sky);
	      double mag = (p2-p1).length();
	      double ang = (p2-p1).angle();
	      str << type_ << '(' << setprecision(8) << v1[0] << ',' << v1[1] 
		  << ','  << ptr->mapLenFromRef(mag,sys,Coord::ARCSEC) << "\""
		  << ',' << radToDeg(parent->mapAngleFromRef(ang,sys,sky)) 
		  << ')';
	    }
	    break;
	  case Coord::SEXAGESIMAL:
	    {
	      char buf[64];
	      char ra1[16];
	      char dec1[16];
	      double mag = (p2-p1).length();
	      double ang = (p2-p1).angle();
	      {
		ptr->mapFromRef(p1,sys,sky,format,buf,64);
		string x(buf);
		istringstream wcs(x);
		wcs >> ra1 >> dec1;
	      }
	      str << type_ << '(' << ra1 << ',' << dec1 
		  << ',' << ptr->mapLenFromRef(mag,sys,Coord::ARCSEC) << "\"" 
		  << ',' << radToDeg(parent->mapAngleFromRef(ang,sys,sky))
		  << ')';
	    }
	    break;
	  }
	}
	else {
	  Vector v1 = ptr->mapFromRef(p1,sys);
	  double mag = (p2-p1).length();
	  double ang = (p2-p1).angle();
	  str << type_ << '(' << setprecision(8) << v1[0] << ',' << v1[1] 
	      << ','  << ptr->mapLenFromRef(mag,sys) 
	      << ',' << radToDeg(parent->mapAngleFromRef(ang,sys)) << ')';
	}
      }
    }

    if (conj)
      str << " ||";

    str << " vector=" << p2Arrow;
    listProperties(str, 0);
  }
}

void Vect::listXML(ostream& str, Coord::CoordSystem sys, Coord::SkyFrame sky, 
		   Coord::SkyFormat format)
{
  FitsImage* ptr = parent->findFits(sys,center);
  double rr = ptr->mapLenFromRef((p2-p1).length(),sys,Coord::ARCSEC);
  
  XMLRowInit();
  XMLRow(XMLSHAPE,type_);

  XMLRowPoint(ptr,sys,sky,format,p1);
  XMLRow(XMLR,rr);
  XMLRowAng(sys,sky);
  XMLRow(XMLPARAM,p2Arrow);

  XMLRowProps(ptr,sys);
  XMLRowEnd(str);
}
