#include "wrap-gphoto.h"
#include "wrap-camera.h"
#include <string.h>

WrapGphoto2::WrapGphoto2()
 : context(NULL),
   portinfolist(NULL) {
   InitGphoto2Data();
}

WrapGphoto2::~WrapGphoto2() {
   gp_context_unref(context);
   if (portinfolist != NULL) {
      gp_port_info_list_free(portinfolist);
      portinfolist = NULL;
   }
   context = NULL;
}

WrapCamera *
WrapGphoto2::OpenCameraOnPort(const char * port) {
   WrapCamera * rval = NULL;
   CameraList *cl = NULL;
   CameraAbilitiesList *abilities = NULL;
   if (gp_abilities_list_new(&abilities) >= GP_OK) {
      if (gp_abilities_list_load(abilities, context) >= GP_OK) {
         if (gp_list_new(&cl) >= GP_OK) {
            if (gp_abilities_list_detect(abilities, portinfolist, cl, context) >= GP_OK) {
               int len = gp_list_count(cl);
               for (int i = 0; i < len; ++i) {
                  const char * name;
                  const char * value;
                  gp_list_get_name(cl, i, &name);
                  gp_list_get_value(cl, i, &value);
                  if (strcmp(value, port) == 0) {
                     // OK, we found the camera on the port of interest.
                     Camera * camera;
                     if (gp_camera_new(&camera) >= GP_OK) {
                        CameraAbilities a;
                        int m = gp_abilities_list_lookup_model(abilities, name);
                        if (m >= GP_OK) {
                           if (gp_abilities_list_get_abilities(abilities, m, &a) >= GP_OK) {
                              if (gp_camera_set_abilities(camera, a) >= GP_OK) {
                                 int p = gp_port_info_list_lookup_path(portinfolist, value);
                                 if (p >= GP_OK) {
                                    GPPortInfo pi;
                                    if (gp_port_info_list_get_info(portinfolist, p, &pi) >= GP_OK) {
                                       if (gp_camera_set_port_info(camera, pi) >= GP_OK) {
                                          rval = new WrapCamera(this, camera);
                                       }
                                    }
                                 }
                              }
                           }
                        }
                     }
                     break;
                  }
               }
            }
            gp_list_free(cl);
         }
      }
      gp_abilities_list_free(abilities);
   }
   return rval;
}

void
WrapGphoto2::InitGphoto2Data() {
   context = gp_context_new();
   if (gp_port_info_list_new(&portinfolist) >= GP_OK) {
      if (gp_port_info_list_load(portinfolist) >= GP_OK) {
         gp_port_info_list_count(portinfolist);
      }
   }
}
