/******************************************************************************
 *
 * Project:  OpenCPN
 * Purpose:  OpenCPN Main wxWidgets Program
 * Author:   David Register
 *
 ***************************************************************************
 *   Copyright (C) 2010 by David S. Register   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,  USA.         *
 ***************************************************************************
 *
 */
#include "wx/wxprec.h"
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif  // precompiled headers
#include "ocpn_types.h"
#include "compasswin.h"
#include "comm_vars.h"
#include "chcanv.h"
#include "styles.h"
#include "wx28compat.h"

BEGIN_EVENT_TABLE(ocpnFloatingCompassWindow, wxWindow)
EVT_PAINT(ocpnFloatingCompassWindow::OnPaint)
    EVT_LEFT_DOWN(ocpnFloatingCompassWindow::MouseEvent) END_EVENT_TABLE()

        extern ocpnStyle::StyleManager* g_StyleManager;
extern bool bGPSValid;
extern bool g_bCourseUp;
extern bool g_bskew_comp;
extern MyFrame* gFrame;

ocpnFloatingCompassWindow::ocpnFloatingCompassWindow(wxWindow* parent) {
  m_pparent = parent;
  long wstyle = wxNO_BORDER | wxFRAME_NO_TASKBAR | wxFRAME_SHAPED;
#ifdef __WXMAC__
  wstyle |= wxSTAY_ON_TOP;
#endif
  wxDialog::Create(parent, -1, _T(""), wxPoint(0, 0), wxSize(-1, -1), wstyle);

  ocpnStyle::Style* style = g_StyleManager->GetCurrentStyle();
  _img_compass = style->GetIcon(_T("CompassRose"));
  _img_gpsRed = style->GetIcon(_T("gpsRed"));

  m_rose_angle = -999;  // force a refresh when first used

  m_pStatBoxToolStaticBmp = NULL;

  m_scale = 1.0;
  SetSize(m_scale *
              ((_img_compass.GetWidth() + _img_gpsRed.GetWidth()) +
               style->GetCompassLeftMargin() * 2 + style->GetToolSeparation()),
          m_scale * (_img_compass.GetHeight() + style->GetCompassTopMargin() +
                     style->GetCompassBottomMargin()));

  m_xoffset = style->GetCompassXOffset();
  m_yoffset = style->GetCompassYOffset();
}

ocpnFloatingCompassWindow::~ocpnFloatingCompassWindow() {
  delete m_pStatBoxToolStaticBmp;
}

void ocpnFloatingCompassWindow::OnPaint(wxPaintEvent& event) {
  int width, height;
  GetClientSize(&width, &height);
  wxPaintDC dc(this);

  dc.DrawBitmap(m_StatBmp, 0, 0, false);
}

void ocpnFloatingCompassWindow::MouseEvent(wxMouseEvent& event) {
  gFrame->ToggleCourseUp();
}

void ocpnFloatingCompassWindow::SetColorScheme(ColorScheme cs) {
  wxColour back_color = GetGlobalColor(_T("GREY2"));

  //  Set background
  SetBackgroundColour(back_color);
  ClearBackground();

  UpdateStatus(true);
}

void ocpnFloatingCompassWindow::UpdateStatus(bool bnew) {
  if (bnew) m_lastgpsIconName.Clear();  // force an update to occur

  wxBitmap statbmp = CreateBmp(bnew);
  if (statbmp.IsOk()) m_StatBmp = statbmp;

  Show();
  Refresh(false);
}

void ocpnFloatingCompassWindow::SetScaleFactor(float factor) {
  //    qDebug() << m_scale << factor;
  ocpnStyle::Style* style = g_StyleManager->GetCurrentStyle();

  if (factor > 0.1)
    m_scale = factor;
  else
    m_scale = 1.0;

  SetSize(m_scale *
              ((_img_compass.GetWidth() + _img_gpsRed.GetWidth()) +
               style->GetCompassLeftMargin() * 2 + style->GetToolSeparation()),
          m_scale * (_img_compass.GetHeight() + style->GetCompassTopMargin() +
                     style->GetCompassBottomMargin()));
}

wxBitmap ocpnFloatingCompassWindow::CreateBmp(bool newColorScheme) {
  wxString gpsIconName;
  ocpnStyle::Style* style = g_StyleManager->GetCurrentStyle();

  // In order to draw a horizontal compass window when the toolbar is vertical,
  // we need to save away the sizes and backgrounds for the two icons.

  static wxBitmap compassBg, gpsBg;
  static wxSize toolsize;
  static int topmargin, leftmargin, radius;

  if (!compassBg.IsOk() || newColorScheme) {
    int orient = style->GetOrientation();
    style->SetOrientation(wxTB_HORIZONTAL);
    if (style->HasBackground()) {
      compassBg = style->GetNormalBG();
      style->DrawToolbarLineStart(compassBg);
      compassBg = style->SetBitmapBrightness(compassBg);
      gpsBg = style->GetNormalBG();
      style->DrawToolbarLineEnd(gpsBg);
      gpsBg = style->SetBitmapBrightness(gpsBg);

      if (fabs(m_scale - 1.0) > 0.1) {
        wxImage bg_img = compassBg.ConvertToImage();
        bg_img.Rescale(compassBg.GetWidth() * m_scale,
                       compassBg.GetHeight() * m_scale, wxIMAGE_QUALITY_NORMAL);
        compassBg = wxBitmap(bg_img);

        bg_img = gpsBg.ConvertToImage();
        bg_img.Rescale(gpsBg.GetWidth() * m_scale, gpsBg.GetHeight() * m_scale,
                       wxIMAGE_QUALITY_NORMAL);
        gpsBg = wxBitmap(bg_img);
      }
    }

    leftmargin = style->GetCompassLeftMargin();
    topmargin = style->GetCompassTopMargin();
    toolsize = style->GetToolSize();
    toolsize.x *= 2;
    radius = style->GetCompassCornerRadius();

    if (orient) style->SetOrientation(wxTB_VERTICAL);
  }

  bool b_need_refresh = false;

  if (bGPSValid) {
    if (g_bSatValid) {
      gpsIconName = _T("gps3Bar");
      if (g_SatsInView <= 8) gpsIconName = _T("gps2Bar");
      if (g_SatsInView <= 4) gpsIconName = _T("gps1Bar");
      if (g_SatsInView < 0) gpsIconName = _T("gpsGry");

    } else
      gpsIconName = _T("gpsGrn");
  } else
    gpsIconName = _T("gpsRed");

  if (m_lastgpsIconName != gpsIconName) b_need_refresh = true;

  double rose_angle = -999.;

  if ((fabs(cc1->GetVPRotation()) > .01) || (fabs(cc1->GetVPSkew()) > .01)) {
    rose_angle = -cc1->GetVPRotation();

    if (!g_bCourseUp && !g_bskew_comp) rose_angle -= cc1->GetVPSkew();

  } else
    rose_angle = 0.;

  if (fabs(m_rose_angle - rose_angle) > .1) b_need_refresh = true;

  if (b_need_refresh) {
    wxBitmap StatBmp;

    StatBmp.Create(
        m_scale *
            ((_img_compass.GetWidth() + _img_gpsRed.GetWidth()) +
             style->GetCompassLeftMargin() * 2 + style->GetToolSeparation()),
        m_scale * (_img_compass.GetHeight() + style->GetCompassTopMargin() +
                   style->GetCompassBottomMargin()));

    if (StatBmp.IsOk()) {
      wxMemoryDC mdc;
      mdc.SelectObject(StatBmp);
      mdc.SetBackground(
          wxBrush(GetGlobalColor(_T("GREY2")), wxBRUSHSTYLE_SOLID));
      mdc.Clear();

      mdc.SetPen(wxPen(GetGlobalColor(_T("UITX1")), 1));
      mdc.SetBrush(
          wxBrush(GetGlobalColor(_T("UITX1")), wxBRUSHSTYLE_TRANSPARENT));

      mdc.DrawRoundedRectangle(0, 0, StatBmp.GetWidth(), StatBmp.GetHeight(),
                               m_scale * style->GetCompassCornerRadius());

      wxPoint offset(style->GetCompassLeftMargin(),
                     style->GetCompassTopMargin());

      wxBitmap iconBm;

      //    Build Compass Rose, rotated...
      wxBitmap BMPRose;
      wxPoint after_rotate;

      if (g_bCourseUp)
        BMPRose = style->GetIcon(_T("CompassRose"));
      else
        BMPRose = style->GetIcon(_T("CompassRoseBlue"));

      if ((fabs(cc1->GetVPRotation()) > .01) ||
          (fabs(cc1->GetVPSkew()) > .01) || (fabs(m_scale - 1.0) > 0.1)) {
        int width = BMPRose.GetWidth() * m_scale;
        int height = BMPRose.GetHeight() * m_scale;

        wxImage rose_img = BMPRose.ConvertToImage();

        if (fabs(m_scale - 1.0) > 0.1)
          rose_img.Rescale(width, height, wxIMAGE_QUALITY_NORMAL);

        if (fabs(rose_angle) > 0.01) {
          wxPoint rot_ctr(width / 2, height / 2);
          wxImage rot_image =
              rose_img.Rotate(rose_angle, rot_ctr, true, &after_rotate);
          BMPRose = wxBitmap(rot_image).GetSubBitmap(
              wxRect(-after_rotate.x, -after_rotate.y, width, height));
        } else
          BMPRose = wxBitmap(rose_img);
      }

      if (style->HasBackground()) {
        iconBm = MergeBitmaps(compassBg, BMPRose, wxSize(0, 0));
      } else {
        iconBm = BMPRose;
      }

      mdc.DrawBitmap(iconBm, offset);
      offset.x += iconBm.GetWidth();

      m_rose_angle = rose_angle;

      //  GPS Icon
      wxBitmap gicon = style->GetIcon(gpsIconName);
      if (fabs(m_scale - 1.0) > 0.1) {
        int width = gicon.GetWidth() * m_scale;
        int height = gicon.GetHeight() * m_scale;

        wxImage gps_img = gicon.ConvertToImage();
        gps_img.Rescale(width, height, wxIMAGE_QUALITY_NORMAL);
        gicon = wxBitmap(gps_img);
      }

      if (style->HasBackground()) {
        iconBm = MergeBitmaps(gpsBg, gicon, wxSize(0, 0));
      } else {
        iconBm = gicon;
      }
      mdc.DrawBitmap(iconBm, offset);
      mdc.SelectObject(wxNullBitmap);
      m_lastgpsIconName = gpsIconName;
    }

#if !defined(__WXMAC__) && !defined(__OCPN__ANDROID__)
    if (style->marginsInvisible) {
      m_MaskBmp = wxBitmap(StatBmp.GetWidth(), StatBmp.GetHeight());
      wxMemoryDC sdc(m_MaskBmp);
      sdc.SetBackground(*wxWHITE_BRUSH);
      sdc.Clear();
      sdc.SetBrush(*wxBLACK_BRUSH);
      sdc.SetPen(*wxBLACK_PEN);
      sdc.DrawRoundedRectangle(wxPoint(leftmargin, topmargin), toolsize,
                               radius);
      sdc.SelectObject(wxNullBitmap);
      SetShape(wxRegion(m_MaskBmp, *wxWHITE, 0));
    } else if (radius) {
      m_MaskBmp = wxBitmap(GetSize().x, GetSize().y);
      wxMemoryDC sdc(m_MaskBmp);
      sdc.SetBackground(*wxWHITE_BRUSH);
      sdc.Clear();
      sdc.SetBrush(*wxBLACK_BRUSH);
      sdc.SetPen(*wxBLACK_PEN);
      sdc.DrawRoundedRectangle(0, 0, m_MaskBmp.GetWidth(),
                               m_MaskBmp.GetHeight(), radius);
      sdc.SelectObject(wxNullBitmap);
      SetShape(wxRegion(m_MaskBmp, *wxWHITE, 0));
    }
#endif

    return StatBmp;
  }

  else
    return wxNullBitmap;
}
