/* 
 * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
 *
 * 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; version 2 of the
 * License.
 * 
 * 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 St, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */

#include "stdafx.h"

#include "mforms/mforms.h"
#include "wf_mforms.h"

#include "wf_view.h"
#include "wf_button.h"
#include "wf_form.h"
#include "wf_checkbox.h"
#include "wf_textentry.h"
#include "wf_textbox.h"
#include "wf_imagebox.h"
#include "wf_label.h"
#include "wf_selector.h"
#include "wf_panel.h"
#include "wf_tabview.h"
#include "wf_box.h"
#include "wf_progressbar.h"
#include "wf_radiobutton.h"
#include "wf_table.h"
#include "wf_filechooser.h"
#include "wf_listbox.h"
#include "wf_wizard.h"
#include "wf_scrollpanel.h"
#include "wf_utilities.h"
#include "wf_drawbox.h"
#include "wf_splitter.h"
#include "wf_webbrowser.h"
#include "wf_popup.h"
#include "wf_menu.h"
#include "wf_menubar.h"
#include "wf_toolbar.h"
#include "wf_code_editor.h"
#include "wf_hypertext.h"
#include "wf_popover.h"
#include "wf_grid.h"
#include "wf_treenodeview.h"
#include "wf_find_panel.h"

#include "wf_appview.h"
#include "wf_app.h"

#include "base/log.h"

using namespace System::Threading;

using namespace MySQL;
using namespace MySQL::Forms;

//--------------------------------------------------------------------------------------------------

Manager::Manager()
{
  created = 0;
  destroyed = 0;

  base::Logger::log(base::Logger::LogInfo, DOMAIN_MFORMS_WRAPPER, "Initializing mforms wrapper\n");

  AppImpl::init(this);
  ViewImpl::init(this);
  FormImpl::init(this);
  ButtonImpl::init(this);
  CheckBoxImpl::init(this);
  TextEntryImpl::init(this);
  TextBoxImpl::init(this);
  LabelImpl::init(this);
  SelectorImpl::init(this);
  PanelImpl::init(this);
  TabViewImpl::init(this);
  BoxImpl::init(this);
  ProgressBarImpl::init(this);
  ImageBoxImpl::init(this);
  RadioButtonImpl::init(this);
  TableImpl::init(this);
  FileChooserImpl::init(this);
  ListBoxImpl::init(this);
  WizardImpl::init(this);
  ScrollPanelImpl::init(this);
  UtilitiesImpl::init(this);
  DrawBoxImpl::init(this);
  AppViewImpl::init(this);
  SplitterImpl::init(this);
  WebBrowserImpl::init(this);
  PopupImpl::init(this);
  MenuImpl::init(this);
  MenuBarImpl::init(this);
  ToolBarImpl::init(this);
  CodeEditorImpl::init(this);
  HyperTextImpl::init(this);
  PopoverImpl::init(this);
  GridImpl::init(this);
  TreeNodeViewImpl::init(this);
  FindPanelImpl::init(this);

//  mforms::ControlFactory::get_instance()->check_impl();
}

//--------------------------------------------------------------------------------------------------

Manager::~Manager()
{
  callbacks.Clear();

  base::Logger::log(base::Logger::LogInfo, DOMAIN_MFORMS_WRAPPER, "Shutting down mforms wrapper\n");
  /* Doesn't really work since on app shutdown many objects are just not regularly freed.
  base::Logger::log(base::Logger::LogDebug2, DOMAIN_MFORMS_WRAPPER,
    "Created %i wrapper objects, destroyed %i, leaking %i objects\n",
    created, destroyed, created - destroyed);
    */
}

//--------------------------------------------------------------------------------------------------

Manager^ MySQL::Forms::Manager::get_instance()
{
  // The manager is created very early in the app startup process from the main thread, so this
  // should never be a concurrency problem here.
  if (singleton == nullptr)
    singleton = gcnew Manager();
  return singleton;
}

//--------------------------------------------------------------------------------------------------

void Manager::instance_created()
{
  // Atomic increment shouldn't be necessary as we always create and destroy wrappers in the
  // main thread. But better safe than sorry.
  Interlocked::Increment(created);
}

//--------------------------------------------------------------------------------------------------

void Manager::instance_destroyed()
{
  Interlocked::Increment(destroyed);
}

//--------------------------------------------------------------------------------------------------

