/**
   * @see IAPClientPaymentListener#productDataListReceived(int,
   *     com.nokia.mid.payment.IAPClientProductData[])
   */
  public final void productDataListReceived(int status, IAPClientProductData[] productDataList) {
    if (status == OK) {
      if (productDataList.length == 0) {
        Util.showAlert("No products", "There are no products available.");
        midlet.showGuideView();
      }

      for (int i = 0, size = productDataList.length; i < size; i++) {
        IAPClientProductData productData = productDataList[i];

        if (productData.getProductId() != null) {
          Guide guideProduct = (Guide) waitingProductData.remove(productData.getProductId());
          String title = productData.getTitle();

          if (title == null) {
            title = productData.getShortDescription();
          }

          if (title == null) {
            title = "unknown";
          }

          String price = productData.getPrice();
          if (price == null) {
            price = "unknown";
          }

          if (guideProduct != null) {
            guideProduct.setCity(title);
            guideProduct.setPrice(price);
            newGuideList.addItem(guideProduct);
            repaint();
          }

          // A guide was clicked before logging in and refreshing
          // the product list. Proceed with the purchase / restore.
          if (newGuide != null && guideProduct.getId().equals(newGuide.getId())) {
            newGuide = null;
            loadingGuides = false;
            handleClickedProduct(guideProduct);
            return;
          }
        }
      }
    } else {
      Util.showAlert("Loading failure", "Loading new guides failed: " + getPaymentError(status));
      midlet.showGuideView();
    }
    waitingProductData = null;
    loadingGuides = false;
    showLoading(false);
    repaint();
  }
  public NewGuideView(TouristMidlet midlet) {
    super(midlet);
    setTitle("Buy guide");
    setLayout(new BorderLayout());
    getStyle().setBgColor(Visual.BACKGROUND_COLOR);

    loadingForm = new Form("Buy guide");
    loadingForm.setLayout(new BorderLayout());
    loadingComp = new LoadingComponent(this);
    loadingForm.addComponent(BorderLayout.CENTER, loadingComp);

    /* See the flow of In-App Purchasing at:
     * http://www.developer.nokia.com/Resources/Library/Java/#!developers-guides/in-app-purchase.html */
    try {
      manager = IAPClientPaymentManager.getIAPClientPaymentManager();
      IAPClientPaymentManager.setIAPClientPaymentListener(this);
    } catch (Exception e) {
      Util.showAlert(e.getClass().getName(), "Could not initialize In-App Purchase manager");
    }

    newGuideList = new NewGuideList(this);
    addComponent(BorderLayout.CENTER, newGuideList);

    loginButton = new Button("Login to see past purchases");
    loginButton.addActionListener(
        new ActionListener() {
          public void actionPerformed(ActionEvent ae) {
            loadAccountAndGuides();
          }
        });
    addCommands();

    revalidate();
  }
  private void addCommands() {
    addCommandListener(this);

    Image mapCommandImage = null;
    if (Compatibility.IS_FULLTOUCH) {
      mapCommandImage = Util.loadImage("icons/map.png");
    }
    mapCommand = new Command("Map", mapCommandImage);
    guidesCommand = new Command("Guides");
    helpCommand = new Command("Help");
    aboutCommand = new Command("About");
    backCommand = new Command("Exit");
    selectCommand = new Command("Select");

    addCommand(mapCommand);
    addCommand(helpCommand);
    addCommand(aboutCommand);

    /* If IAP not supported, no need to get to the guides view */
    if (Compatibility.IAP_SUPPORTED) {
      addCommand(guidesCommand);
    }

    if (!Compatibility.TOUCH_SUPPORTED) {
      addCommand(selectCommand);
      setDefaultCommand(selectCommand);
    } else {
      setDefaultCommand(mapCommand);
    }

    addCommand(backCommand);
    setBackCommand(backCommand);
  }
  public void actionPerformed(ActionEvent e) {
    Command cmd = e.getCommand();
    if (cmd != null) {
      // Free some memory
      freeThumbnails();
    }

    /* Handle different commands */
    if (cmd == aboutCommand) {
      midlet.showAboutView();
    } else if (cmd == helpCommand) {
      midlet.showHelpView();
    } else if (cmd == guidesCommand) {
      midlet.showGuideView();
    } else if (cmd == mapCommand) {
      GeoCoordinate loc = Self.getCurrentPosition();
      if (loc != null) {
        midlet.showMapView(guide, null, loc.getLatitude(), loc.getLongitude(), "My location");
      } else {
        Util.showAlert("Location error", "Could not get your location.");
      }
    } else if (cmd == selectCommand) {
      attractionList.actionPerformed(new ActionEvent(attractionList));
    } else if (cmd == backCommand) {
      Display.getInstance().exitApplication();
    }
  }
 /**
  * Purchases a guide.
  *
  * @param guide Guide to be purchased.
  */
 public void purchase(Guide guide) {
   int status =
       manager.purchaseProduct(
           guide.getId(), IAPClientPaymentManager.FORCED_AUTOMATIC_RESTORATION);
   if (status != IAPClientPaymentManager.SUCCESS) {
     guide = null;
     Util.showAlert("Purchase failure", getPaymentError(status));
   }
 }
 /**
  * @see IAPClientPaymentListener#userAndDeviceDataReceived(int,
  *     com.nokia.mid.payment.IAPClientUserAndDeviceData)
  */
 public final void userAndDeviceDataReceived(int status, IAPClientUserAndDeviceData ud) {
   loadingAccount = false;
   if (status == OK) {
     account = ud.getAccount();
     loadGuides();
   } else {
     Util.showAlert("Authorization failure", getPaymentError(status));
     showLoading(false);
   }
 }
 /** @see IAPClientPaymentListener#restorationCompleted(int, java.lang.String) */
 public final void restorationCompleted(int status, String purchaseTicket) {
   switch (status) {
     case OK:
       guidePurchased(purchaseTicket);
       break;
     default:
       newGuide = null;
       Util.showAlert("Restoration failure", getPaymentError(status));
       break;
   }
 }
 /** @see IAPClientPaymentListener#purchaseCompleted(int, java.lang.String) */
 public final void purchaseCompleted(int status, String purchaseTicket) {
   switch (status) {
     case OK:
       guidePurchased(purchaseTicket);
       break;
     case RESTORABLE:
       guidePurchased(purchaseTicket == null ? "" : purchaseTicket);
       break;
     default:
       newGuide = null;
       Util.showAlert("Purchase failure", getPaymentError(status));
       break;
   }
 }
  private void loadAccountAndGuides() {
    if (loadingAccount) {
      return;
    }

    loadingAccount = true;
    showLoading(true);

    // For restoring guides user's account is needed
    int status = manager.getUserAndDeviceId(IAPClientPaymentManager.DEFAULT_AUTHENTICATION);

    if (status != IAPClientPaymentManager.SUCCESS) {
      Util.showAlert("Authorization failure", getPaymentError(status));
      newGuide = null;
      loadingAccount = false;
    }
  }
  private void loadProductData() {
    if (waitingProductData.isEmpty()) {
      waitingProductData = null;
      loadingGuides = false;
      return;
    }

    String[] productIds = new String[waitingProductData.size()];
    Enumeration e = waitingProductData.keys();

    for (int i = 0; e.hasMoreElements(); i++) {
      productIds[i] = ((String) e.nextElement());
    }

    int status = manager.getProductData(productIds);
    if (status != IAPClientPaymentManager.SUCCESS) {
      waitingProductData = null;
      Util.showAlert("Metadata failure", getPaymentError(status));
      midlet.showGuideView();
      loadingGuides = false;
    }
  }