content: /*
   * CDDL HEADER START
   *
   * The contents of this file are subject to the terms of the Common Development
   * and Distribution License (the "License").
   * You may not use this file except in compliance with the License.
   *
   * You can obtain a copy of the license at
   * src/com/vodafone360/people/VODAFONE.LICENSE.txt or
   * http://github.com/360/360-Engine-for-Android
   * See the License for the specific language governing permissions and
   * limitations under the License.
   *
   * When distributing Covered Code, include this CDDL HEADER in each file and
   * include the License file at src/com/vodafone360/people/VODAFONE.LICENSE.txt.
   * If applicable, add the following below this CDDL HEADER, with the fields
   * enclosed by brackets "[]" replaced with your own identifying information:
   * Portions Copyright [yyyy] [name of copyright owner]
   *
   * CDDL HEADER END
   *
   * Copyright 2010 Vodafone Sales & Services Ltd.  All rights reserved.
   * Use is subject to license terms.
   */
  
  package com.vodafone360.people.engine.upgrade;
  
  import java.io.BufferedReader;
  import java.io.IOException;
  import java.io.InputStreamReader;
  import java.net.MalformedURLException;
  import java.net.URL;
  import java.net.URLConnection;
  
  import android.content.Context;
  
  import com.vodafone360.people.Settings;
  import com.vodafone360.people.SettingsManager;
  import com.vodafone360.people.engine.BaseEngine;
  import com.vodafone360.people.engine.IEngineEventCallback;
  import com.vodafone360.people.engine.EngineManager.EngineId;
  import com.vodafone360.people.service.ServiceStatus;
  import com.vodafone360.people.service.ServiceUiRequest;
  import com.vodafone360.people.service.agent.NetworkAgent;
  import com.vodafone360.people.service.agent.NetworkAgent.AgentState;
  import com.vodafone360.people.service.io.ResponseQueue.DecodedResponse;
  import com.vodafone360.people.utils.CloseUtils;
  import com.vodafone360.people.utils.LogUtils;
  import com.vodafone360.people.utils.VersionUtils;
  
  /**
   * Checks Settings.UPGRADE_CHECK_URL for information on a software upgrade .
   * Triggers a dialog in the UI when a newer application version is available
   * Throttles UI events
   */
  public class UpgradeEngine extends BaseEngine {
  
      private Context mContext;
  
      private UpgradeStatus mUpgradeStatus;
  
      private long mCheckFrequencyMillis;
  
      private long mNextRunTime = 0; // Run once
  
      private boolean mForceOnce = false;
  
      private boolean mActivated = false;
  
      private UpgradeEngineNetworkThread mUpgradeEngineNetworkThread;
  
      /**
       * Constructor.
       * 
       * @param context - the context to use
       * @param eventCallback - the engine event client to use
       */
      public UpgradeEngine(Context context, IEngineEventCallback eventCallback) {
          super(eventCallback);
          mActivated = SettingsManager.getProperty(Settings.UPGRADE_CHECK_URL_KEY) != null;
          mEngineId = EngineId.UPGRADE_ENGINE;
          mContext = context;
          mCheckFrequencyMillis = UpgradeUtils.getCheckFrequency(context);
      }
  
      /**
       * Return the mNextRunTime value if the feature is enabled.
       * 
       * @return the mNextRunTime value if the feature is enabled.
       */
      @Override
      public long getNextRunTime() {
          if (!mActivated) {
              LogUtils.logV("UpgradeEngine.getNextRunTime() Not currently activated");
              return -1;
          }
          if (isUiRequestOutstanding()) {
              return 0;
          }
          if (NetworkAgent.getAgentState() != AgentState.CONNECTED) {
              LogUtils.logD("UpgradeEngine.getNextRunTime() Not currently connected");
              return -1;
          }
  
          if (mForceOnce) {
              LogUtils.logD("UpgradeEngine.getNextRunTime() Engine forced to run");
              return 0;
  
          } else if (mCheckFrequencyMillis == -1) {
              LogUtils.logD("UpgradeEngine.getNextRunTime() Upgrade feature disabled");
              return -1;
  
          } else {
              // LogUtils.logV("UpgradeEngine.getNextRunTime() Returning [" +
              // mNextRunTime + "] or in ["+(mNextRunTime -
              // System.currentTimeMillis())+"ms]");
              return mNextRunTime;
          }
      }
  
      /**
       * Trigger the UpgradeEngineNetworkThread if the feature is enabled.
       */
      @Override
      public void run() {
          if (!mActivated) {
              LogUtils.logE("UpgradeEngine.getNextRunTime() Not currently activated");
              return;
          }
          if (NetworkAgent.getAgentState() != AgentState.CONNECTED) {
              LogUtils.logE("UpgradeEngine.getNextRunTime() Not currently connected");
              return;
          }
  
          if (isUiRequestOutstanding() && processUiQueue()) {
              return;
          }
          if (!mForceOnce && mCheckFrequencyMillis == -1) {
              LogUtils.logD("UpgradeEngine.run() Upgrade feature disabled");
              return;
          } else {
              if (mUpgradeEngineNetworkThread == null || !mUpgradeEngineNetworkThread.isRunning()) {
                  // LogUtils.logV("UpgradeEngine.run() Start the UpgradeEngineNetworkThread mForceOnce["
                  // + mForceOnce + "]");
                  mUpgradeEngineNetworkThread = new UpgradeEngineNetworkThread();
                  mUpgradeEngineNetworkThread.start();
              } else {
                  LogUtils.logD("UpgradeEngine.run() UpgradeEngineNetworkThread already running["
                          + mForceOnce + "]");
              }
          }
  
          setNextRuntime();
      }
  
      private void setNextRuntime() {
          mForceOnce = false;
          if (mCheckFrequencyMillis != -1) {
              mNextRunTime = System.currentTimeMillis() + mCheckFrequencyMillis;
              // LogUtils.logV("UpgradeEngine.setNextRuntime() Run again at [" +
              // mNextRunTime + "] or in ["+(mNextRunTime -
              // System.currentTimeMillis())+"ms], mCheckFrequencyMillis["+mCheckFrequencyMillis+"ms]");
          } else {
              LogUtils.logV("UpgradeEngine.setNextRuntime() mCheckFrequencyMillis["
                      + mCheckFrequencyMillis + "] so return -1");
              mNextRunTime = -1;
          }
      }
  
      /**
       * Thread for running an upgrade check without blocking the WorkerThread.
       */
      private class UpgradeEngineNetworkThread extends Thread {
          private static final String UPGRADE_THREAD_NAME = "UpgradeThread";
  
          private boolean mRunning = true;
  
          public UpgradeEngineNetworkThread() {
              setName(UPGRADE_THREAD_NAME);
          }
  
          /**
           * Check the Settings.UPGRADE_CHECK_URL file for information on a new
           * software upgrade.
           */
          @Override
          public void run() {
              LogUtils.logI("UpgradeEngine.UpgradeEngineNetworkThread.run() [Start Thread]");
  
              mUpgradeStatus = new UpgradeStatus();
              BufferedReader mBufferedReader = null;
              try {
                  URL mUrl = new URL(SettingsManager.getProperty(Settings.UPGRADE_CHECK_URL_KEY)
                          + "?currentversion=" + VersionUtils.getPackageVersionCode(mContext));
                  LogUtils.logV("UpgradeEngine.UpgradeEngineNetworkThread.run() Checking URL ["
                          + mUrl + "]");
                  URLConnection mURLConnection = mUrl.openConnection();
                  mBufferedReader = new BufferedReader(new InputStreamReader(mURLConnection
                          .getInputStream(), "UTF-8"));
                  String mLine;
                  while ((mLine = mBufferedReader.readLine()) != null) {
                      mUpgradeStatus.addSetting(mLine);
                  }
                  mBufferedReader.close();
  
                  if (mUpgradeStatus.getLatestVersion() > VersionUtils.getPackageVersionCode(mContext)) {
  
                      // Show upgrade dialog
                      LogUtils.logD("UpgradeEngine.UpgradeEngineNetworkThread.run() New Version ["
                              + mUpgradeStatus.getLatestVersion() + "] better than current ["
                              + VersionUtils.getPackageVersionCode(mContext) + "]");
  
                  } else {
                      // Do nothing
                      LogUtils.logV("UpgradeEngine.UpgradeEngineNetworkThread.run() New Version ["
                              + mUpgradeStatus.getLatestVersion() + "] is not better than current ["
                              + VersionUtils.getPackageVersionCode(mContext) + "]");
                      mUpgradeStatus = null;
                  }
                  UpgradeUtils.cacheUpdate(mContext, mUpgradeStatus);
  
                  // Request to update the UI
                  completeUiRequest(ServiceStatus.SUCCESS, null);
  
                  if (mUpgradeStatus != null) {
                      mEventCallback.getUiAgent().sendUnsolicitedUiEvent(
                              ServiceUiRequest.UNSOLICITED_DIALOG_UPGRADE, null);
                  }
  
              } catch (MalformedURLException e) {
                  LogUtils.logE(
                          "UpgradeEngine.UpgradeEngineNetworkThread.run() MalformedURLException", e);
  
              } catch (IOException e) {
                  LogUtils.logE("UpgradeEngine.UpgradeEngineNetworkThread.run() IOException", e);
  
              } finally {
                  CloseUtils.close(mBufferedReader);
              }
              mRunning = false;
              LogUtils.logI("UpgradeEngine.UpgradeEngineNetworkThread.run() [Stop Thread]");
          }
  
          public boolean isRunning() {
              return mRunning;
          }
      }
  
      @Override
      protected void processUiRequest(ServiceUiRequest requestId, Object data) {
          switch (requestId) {
              case UPGRADE_CHECK_NOW:
                  // Ensure that the UpgradeEngine will run the next time the
                  // WorkerThread is kicked
                  LogUtils.logW("UpgradeEngine.processUiRequest() UPGRADE_CHECK_NOW");
                  mForceOnce = true;
                  break;
              case UPGRADE_CHANGE_FREQUENCY:
                  mCheckFrequencyMillis = UpgradeUtils.getCheckFrequency(mContext);
                  mNextRunTime = System.currentTimeMillis() + mCheckFrequencyMillis;
                  LogUtils.logW("UpgradeEngine.processUiRequest() mCheckFrequencyMillis["
                          + mCheckFrequencyMillis + "] mNextRunTime[" + mNextRunTime + "]");
                  break;
              default:
                  // Do nothing.
                  break;
          }
      }
  
      @Override
      public void onCreate() {
          // Do nothing
      }
  
      @Override
      public void onDestroy() {
          // Do nothing
      }
  
      @Override
      protected void onRequestComplete() {
          // Do nothing
      }
  
      @Override
      protected void onTimeoutEvent() {
          // Do nothing
      }
  
      @Override
      protected void processCommsResponse(DecodedResponse resp) {
          // Do nothing
      }
  
      /**
       * Sets a new value for the frequency with which to check for application
       * updates.
       */
      public void setNewUpdateFrequency() {
          LogUtils.logD("UpgradeEngine.setNewUpdateFrequency()");
          addUiRequestToQueue(ServiceUiRequest.UPGRADE_CHANGE_FREQUENCY, null);
      }
  
      /**
       * Add request to check for application update.
       */
      public void checkForUpdates() {
          LogUtils.logD("UpgradeEngine.checkForUpdates()");
          addUiRequestToQueue(ServiceUiRequest.UPGRADE_CHECK_NOW, null);
      }
  }
  