// Filename: panda3d.h
// Created by:  drose (30Jun09)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University.  All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license.  You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////

#ifndef PANDA3D_H
#define PANDA3D_H

// This program must link with Panda for HTTPClient support.  This
// means it probably should be built with LINK_ALL_STATIC defined, so
// we won't have to deal with confusing .dll or .so files that might
// compete on the disk with the dynamically-loaded versions.  There's
// no competition in memory address space, though, because
// p3d_plugin--the only file we dynamically link in--doesn't itself
// link with Panda.

#include "pandabase.h"
#include "p3d_plugin.h"
#include "httpChannel.h"
#include "ramfile.h"
#include "fileSpec.h"
#include "pset.h"
#include "vector_string.h"

////////////////////////////////////////////////////////////////////
//       Class : Panda3D
// Description : A standalone program that invokes the Panda3D plugin
//               to launch .p3d files.
////////////////////////////////////////////////////////////////////
class Panda3D {
public:
  Panda3D(bool console_environment);

  int run_command_line(int argc, char *argv[]);
  void run_main_loop();

protected:
  bool post_arg_processing();
  bool get_plugin();
  bool read_contents_file(const Filename &contents_filename);
  void find_host(TiXmlElement *xcontents);
  void read_xhost(TiXmlElement *xhost);
  void add_mirror(string mirror_url);
  void choose_random_mirrors(vector_string &result, int num_mirrors);
  bool get_core_api(const Filename &contents_filename, TiXmlElement *xplugin);
  void run_getters();
  void handle_request(P3D_request *request);
  void make_parent_window();

  P3D_instance *
  create_instance(const string &p3d, bool start_instance,
                  int win_x, int win_y, int win_width, int win_height,
                  char **args, int num_args);
  void delete_instance(P3D_instance *instance);

  void usage();
  bool parse_token(char *arg);
  bool parse_int_pair(char *arg, int &x, int &y);
  static bool is_url(const string &param);

  void report_downloading_package(P3D_instance *instance);
  void report_download_complete(P3D_instance *instance);

  inline bool time_to_exit();

#ifdef __APPLE__
  static pascal void st_timer_callback(EventLoopTimerRef timer, void *user_data);
  void timer_callback(EventLoopTimerRef timer);
#endif

protected:
  string _root_dir;
  string _log_dirname;
  string _log_basename;
  string _this_platform;
  bool _verify_contents;
  P3D_window_type _window_type;
  P3D_window_handle _parent_window;
  int _win_x, _win_y;
  int _win_width, _win_height;
  bool _exit_with_last_instance;

  string _host_url;
  string _super_mirror_url;
  string _host_url_prefix;
  string _download_url_prefix;
  string _super_mirror_url_prefix;
  typedef pvector<string> Mirrors;
  Mirrors _mirrors;
  
  FileSpec _core_api_dll;
  bool _reporting_download;
  bool _enable_security;
  bool _console_environment;

  typedef pset<P3D_instance *> Instances;
  Instances _instances;

  typedef pvector<P3D_token> Tokens;
  Tokens _tokens;

  // This nested class keeps track of active URL requests.
  class URLGetter {
  public:
    URLGetter(P3D_instance *instance, int unique_id,
              const URLSpec &url, const string &post_data);
    
    bool run();
    inline P3D_instance *get_instance();
    
  private:
    P3D_instance *_instance;
    int _unique_id;
    URLSpec _url;
    string _post_data;
    
    PT(HTTPChannel) _channel;
    Ramfile _rf;
    size_t _bytes_sent;
  };
  
  typedef pset<URLGetter *> URLGetters;
  URLGetters _url_getters;
};

#include "panda3d.I"

#endif

