#include "CosNamingC.h"

#include "Naming/video/Naming.h"

#include <tao/corba.h>

#include "Common/ServerC.h"

/*
 * @func This program resolves a reference to the Naming Service
 * and finds a video supplier object in a lookup for a given video
 * title.
 */
int
main (int argc, char **argv)
{
  try
    {
      // Initialise the ORB.
      CORBA::ORB_var orbVar = CORBA::ORB_init (argc, argv);
      ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("INFO: Initialised ORB\n")));

      // Get a reference to the naming service.
      CORBA::Object_var objVar =
        orbVar->resolve_initial_references (ACE_TEXT ("NameService"));
      CosNaming::NamingContext_var rootContextVar =
        CosNaming::NamingContext::_narrow (objVar.in ());
      if (CORBA::is_nil (rootContextVar.in ()))
        {
          ACE_ERROR_RETURN ((LM_ERROR,
                             ACE_TEXT ("ERROR: Nil reverence\n")),
                            1);
        }

      // Prepare name context to service provider binding.
      CosNaming::Name rootName;
      rootName.length (1);
      rootName[0].id = CORBA::string_dup (ACE_TEXT ("ServiceProvider"));
      rootName[0].kind = CORBA::string_dup (ACE_TEXT ("server"));

      // Resolve service provider (server) from naming service.
      CORBA::Object_var serverVar;
      Naming::resolveToObject (rootName, rootContextVar.in (), serverVar.out ());

      // Narrow server to ServiceProvider implementation.
      Server::ServiceProvider_var providerVar =
        Server::ServiceProvider::_narrow (serverVar.in ());
      if (CORBA::is_nil (providerVar.in ()))
        {
          ACE_ERROR_RETURN ((LM_ERROR,
                             ACE_TEXT ("ERROR: Resolved to a null VideoServiceProvider object\n")),
                            1);
        }

      // Retrieve the list of companies from the service provider.
      Server::CompanyNameList_var listVar = providerVar->getCompanies ();
      if (listVar->length () > 0)
        {
          ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Available companies:-\n")));
          for (CORBA::ULong count = 0; count < listVar->length (); ++count)
            {
              ACE_DEBUG ((LM_DEBUG,
                          ACE_TEXT ("%s\n"),
                          ((*listVar)[count]).in ()));
            }

          // Resolve an arbitary company from the naming service.
          CosNaming::Name companyName;
          companyName.length (3);
          companyName[0].id =
            CORBA::string_dup (ACE_TEXT ("Video Stream Supplier"));
          companyName[1].id =
            CORBA::string_dup (ACE_TEXT ("Films"));
          companyName[2].id =
            CORBA::string_dup (ACE_TEXT ("Videos for Sale"));

          CORBA::Object_var myObjectVar;
          Naming::resolveToObject (companyName, rootContextVar.in (), myObjectVar.out ());
          if (CORBA::is_nil (myObjectVar.in ()))
            {
              ACE_ERROR_RETURN ((LM_ERROR,
                                 ACE_TEXT ("ERROR: Could not resolve to the chosen company\n")),
                                1);
            }

          Server::Company_var companyVar =
            Server::Company::_narrow (myObjectVar.in ());
          if (CORBA::is_nil (companyVar.in ()))
            {
              ACE_ERROR_RETURN ((LM_ERROR,
                                 ACE_TEXT ("ERROR: Narrowed to a null company\n")),
                                1);
            }

          // Retrieve the list of offered films from the company.
          CORBA::String_var catVar = CORBA::string_dup (ACE_TEXT ("Films"));
          Server::OfferList_var offersVar =
            companyVar->getOffers (catVar.in ());
          if (offersVar->length () > 0)
            {
              ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Available 'Films' feeds:\n")));
              for (CORBA::ULong count2 = 0; count2 < offersVar->length (); ++count2)
                {
                  ACE_DEBUG ((LM_DEBUG,
                              ACE_TEXT ("%s\n"),
                              ((*offersVar)[count2]).in ()));
                }
            }
          else
            {
              ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Null list of offers returned\n")));
            }
        }
      else
        {
          ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Null list of companies returned\n")));
        }

      orbVar->destroy ();
    }
  catch (const CORBA::Exception &ex)
    {
      ex._tao_print_exception (ACE_TEXT ("ERROR: Exception in NamingClient.cpp:"));
      return 1;
    }

  // Complete.
  return 0;
}
