// Copyright 2008-2010 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========================================================================

#include "omaha/worker/job_creator.h"

#include <windows.h>
#include <atlcom.h>
#include <cstring>
#include <map>
#include "omaha/common/debug.h"
#include "omaha/common/error.h"
#include "omaha/common/file.h"
#include "omaha/common/logging.h"
#include "omaha/common/path.h"
#include "omaha/common/time.h"
#include "omaha/goopdate/config_manager.h"
#include "omaha/goopdate/const_goopdate.h"
#include "omaha/goopdate/goopdate_xml_parser.h"
#include "omaha/goopdate/request.h"
#include "omaha/goopdate/resource.h"
#include "omaha/goopdate/update_response_data.h"
#include "omaha/worker/application_data.h"
#include "omaha/worker/ping.h"
#include "omaha/worker/worker_event_logger.h"
#include "omaha/worker/worker_metrics.h"

namespace omaha {

HRESULT JobCreator::CreateJobsFromResponses(
    const UpdateResponses& responses,
    const ProductDataVector& products,
    Jobs* jobs,
    Request* ping_request,
    CString* event_log_text,
    CompletionInfo* completion_info) {
  ASSERT1(jobs);
  ASSERT1(ping_request);
  ASSERT1(event_log_text);
  ASSERT1(completion_info);
  CORE_LOG(L2, (_T("[JobCreator::CreateJobsFromResponses]")));

  // First check to see if GoogleUpdate update is available, if so we only
  // create the job for googleupdate and don't create jobs for the rest.
  if (IsGoopdateUpdateAvailable(responses)) {
    return CreateGoopdateJob(responses,
                             products,
                             jobs,
                             ping_request,
                             event_log_text,
                             completion_info);
  }

  return CreateJobsFromResponsesInternal(responses,
                                         products,
                                         jobs,
                                         ping_request,
                                         event_log_text,
                                         completion_info);
}

bool JobCreator::IsGoopdateUpdateAvailable(const UpdateResponses& responses) {
  UpdateResponses::const_iterator iter = responses.find(kGoopdateGuid);
  if (iter == responses.end()) {
    return false;
  }

  const UpdateResponse& update_response = iter->second;
  return (_tcsicmp(kResponseStatusOkValue,
                   update_response.update_response_data().status()) == 0);
}

void JobCreator::AddAppUpdateDeferredPing(const AppData& product_data,
                                          Request* ping_request) {
  ASSERT1(ping_request);

  AppRequest ping_app_request;
  AppRequestData ping_app_request_data(product_data);
  PingEvent ping_event(PingEvent::EVENT_UPDATE_COMPLETE,
                       PingEvent::EVENT_RESULT_UPDATE_DEFERRED,
                       0,
                       0,  // extra code 1
                       product_data.previous_version());
  ping_app_request_data.AddPingEvent(ping_event);
  ping_app_request.set_request_data(ping_app_request_data);
  ping_request->AddAppRequest(ping_app_request);
}

HRESULT JobCreator::CreateGoopdateJob(const UpdateResponses& responses,
                                      const ProductDataVector& products,
                                      Jobs* jobs,
                                      Request* ping_request,
                                      CString* event_log_text,
                                      CompletionInfo* completion_info) {
  ASSERT1(jobs);
  ASSERT1(ping_request);
  ASSERT1(event_log_text);
  ASSERT1(completion_info);

  UpdateResponses::const_iterator it = responses.find(kGoopdateGuid);
  if (it == responses.end()) {
    return E_INVALIDARG;
  }

  UpdateResponses goopdate_responses;
  goopdate_responses[kGoopdateGuid] = it->second;

  // Create a job for GoogleUpdate only and defer updates for other products,
  // if updates are available.
  ProductDataVector goopdate_products;
  bool is_other_app_update_available(false);
  for (size_t i = 0; i < products.size(); ++i) {
    const GUID app_id = products[i].app_data().app_guid();
    if (::IsEqualGUID(app_id, kGoopdateGuid)) {
      goopdate_products.push_back(products[i]);
    } else {
      it = responses.find(app_id);
      if (it != responses.end() && IsUpdateAvailable(it->second)) {
        is_other_app_update_available = true;
        AddAppUpdateDeferredPing(products[i].app_data(), ping_request);
      }
    }
  }
  ASSERT1(goopdate_products.size() == 1);

  if (is_other_app_update_available) {
    ++metric_worker_skipped_app_update_for_self_update;
  }

  return CreateJobsFromResponsesInternal(goopdate_responses,
                                         goopdate_products,
                                         jobs,
                                         ping_request,
                                         event_log_text,
                                         completion_info);
}

HRESULT JobCreator::ReadOfflineManifest(const CString& offline_dir,
                                        const CString& app_guid,
                                        UpdateResponse* response) {
  ASSERT1(response);

  CString manifest_filename = app_guid + _T(".gup");
  CString manifest_path = ConcatenatePath(offline_dir, manifest_filename);
  if (!File::Exists(manifest_path)) {
    return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  }

  UpdateResponses responses;
  HRESULT hr = GoopdateXmlParser::ParseManifestFile(manifest_path, &responses);
  if (FAILED(hr)) {
    OPT_LOG(LE, (_T("[Could not parse manifest][%s]"), manifest_path));
    return hr;
  }
  ASSERT1(!responses.empty());
  ASSERT1(1 == responses.size());

  UpdateResponses::const_iterator iter = responses.begin();
  *response = iter->second;
  ASSERT1(!app_guid.CompareNoCase(GuidToString(
      response->update_response_data().guid())));
  return S_OK;
}

HRESULT JobCreator::FindOfflineFilePath(const CString& offline_dir,
                                        const CString& app_guid,
                                        CString* file_path) {
  ASSERT1(file_path);
  file_path->Empty();

  CString offline_app_dir = ConcatenatePath(offline_dir, app_guid);
  CString pattern(_T("*"));
  std::vector<CString> files;
  HRESULT hr = FindFiles(offline_app_dir, pattern, &files);
  if (FAILED(hr)) {
    return hr;
  }

  CString local_file_path;
  // Skip over "." and "..".
  size_t i = 0;
  for (; i < files.size(); ++i) {
    local_file_path = ConcatenatePath(offline_app_dir, files[i]);
    if (!File::IsDirectory(local_file_path)) {
      break;
    }
  }
  if (i == files.size()) {
    return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  }

  *file_path = local_file_path;
  return S_OK;
}

HRESULT JobCreator::CreateOfflineJobs(const CString& offline_dir,
                                      const ProductDataVector& products,
                                      Jobs* jobs,
                                      Request* ping_request,
                                      CString* event_log_text,
                                      CompletionInfo* completion_info) {
  CORE_LOG(L2, (_T("[JobCreator::CreateOfflineJobs]")));
  ASSERT1(jobs);
  ASSERT1(ping_request);
  ASSERT1(event_log_text);
  ASSERT1(completion_info);

  ProductDataVector::const_iterator products_it = products.begin();
  for (; products_it != products.end(); ++products_it) {
    const ProductData& product_data = *products_it;
    CString guid(GuidToString(product_data.app_data().app_guid()));
    UpdateResponse response;
    CString file_path;

    HRESULT hr = ReadOfflineManifest(offline_dir, guid, &response);
    if (SUCCEEDED(hr)) {
      hr = FindOfflineFilePath(offline_dir, guid, &file_path);
    }
    if (SUCCEEDED(hr)) {
      hr = goopdate_utils::ValidateDownloadedFile(
               file_path,
               response.update_response_data().hash(),
               static_cast<uint32>(response.update_response_data().size()));
    }
    if (FAILED(hr)) {
      *completion_info = CompletionInfo(COMPLETION_ERROR, hr, _T(""));
      return hr;
    }

    Job* product_job = NULL;
    hr = HandleProductUpdateIsAvailable(product_data,
                                        response,
                                        &product_job,
                                        ping_request,
                                        event_log_text,
                                        completion_info);
    if (FAILED(hr)) {
      return hr;
    }

    product_job->set_download_file_name(file_path);
    product_job->set_is_offline(true);
    jobs->push_back(product_job);
  }

  return S_OK;
}

HRESULT JobCreator::CreateJobsFromResponsesInternal(
    const UpdateResponses& responses,
    const ProductDataVector& products,
    Jobs* jobs,
    Request* ping_request,
    CString* event_log_text,
    CompletionInfo* completion_info) {
  ASSERT1(jobs);
  ASSERT1(ping_request);
  ASSERT1(event_log_text);
  ASSERT1(completion_info);
  CORE_LOG(L2, (_T("[JobCreator::CreateJobsFromResponsesInternal]")));

  // The ordering needs to be done based on the products array, instead of
  // basing this on the responses. This is because the first element in the
  // job that is created is considered the primary app.
  ProductDataVector::const_iterator products_it = products.begin();
  for (; products_it != products.end(); ++products_it) {
    const ProductData& product_data = *products_it;
    AppData product_app_data = product_data.app_data();

    UpdateResponses::const_iterator iter =
        responses.find(product_app_data.app_guid());
    if (iter == responses.end()) {
      AppRequestData ping_app_request_data(product_app_data);
      HandleResponseNotFound(product_app_data,
                             &ping_app_request_data,
                             event_log_text);
      continue;
    }

    const UpdateResponse& response = iter->second;

    AppManager app_manager(is_machine_);
    // If this is an update job, need to call
    // AppManager::UpdateApplicationState() to make sure the registry is
    // initialized properly.
    if (is_update_) {
      app_manager.UpdateApplicationState(&product_app_data);
    }

    // Write the TT Token, if any, with what the server returned. The server
    // may ask us to clear the token as well.
    app_manager.WriteTTToken(product_app_data, response.update_response_data());

    if (IsUpdateAvailable(response)) {
      if (product_data.app_data().is_update_disabled()) {
        ASSERT1(is_update_);
        ASSERT1(!fail_if_update_not_available_);
        CORE_LOG(L1, (_T("[Update available for update-disabled app][%s]"),
                      GuidToString(product_data.app_data().app_guid())));
        app_manager.ClearUpdateAvailableStats(
            GUID_NULL,
            product_data.app_data().app_guid());
      } else {
        ProductData modified_product_data(product_data);
        modified_product_data.set_app_data(product_app_data);
        Job* product_job = NULL;
        HRESULT hr = HandleProductUpdateIsAvailable(modified_product_data,
                                                    response,
                                                    &product_job,
                                                    ping_request,
                                                    event_log_text,
                                                    completion_info);
        if (FAILED(hr)) {
          return hr;
        }

        jobs->push_back(product_job);
      }
    } else {
      AppRequest ping_app_request;
      AppRequestData ping_app_request_data(product_app_data);
      HRESULT hr = HandleUpdateNotAvailable(product_app_data,
                                            response.update_response_data(),
                                            &ping_app_request_data,
                                            event_log_text,
                                            completion_info);
      // TODO(omaha): It's unclear why the ping is added before the FAILED
      // check here but after it in HandleProductUpdateIsAvailable(). Is this
      // intentional?
      ping_app_request.set_request_data(ping_app_request_data);
      ping_request->AddAppRequest(ping_app_request);
      if (FAILED(hr)) {
        return hr;
      }
    }
  }

  return S_OK;
}

HRESULT JobCreator::HandleProductUpdateIsAvailable(
    const ProductData& product_data,
    const UpdateResponse& response,
    Job** product_job,
    Request* ping_request,
    CString* event_log_text,
    CompletionInfo* completion_info) {
  ASSERT1(product_job);

  AppData product_app_data = product_data.app_data();
  AppRequest ping_app_request;
  AppRequestData ping_app_request_data(product_app_data);

  if (is_update_) {
    // previous_version should have been populated above.
    ASSERT1(!product_app_data.previous_version().IsEmpty());
  } else {
    // Copy the current version of app, if available, to previous version
    // in the AppData object so it is sent in pings.
    AppData existing_app_data;
    AppManager app_manager(is_machine_);
    HRESULT hr = app_manager.ReadAppDataFromStore(
                     GUID_NULL,
                     product_app_data.app_guid(),
                     &existing_app_data);
    if (SUCCEEDED(hr)) {
      product_app_data.set_previous_version(existing_app_data.version());
    }
  }

  ASSERT1(::IsEqualGUID(GUID_NULL, product_app_data.parent_app_guid()));
  HandleUpdateIsAvailable(product_app_data,
                          response.update_response_data(),
                          &ping_app_request_data,
                          event_log_text,
                          product_job);
  ASSERT1(*product_job);
  ping_app_request.set_request_data(ping_app_request_data);

  ping_request->AddAppRequest(ping_app_request);
  return S_OK;
}

void JobCreator::HandleResponseNotFound(const AppData& app_data,
                                        AppRequestData* ping_app_request_data,
                                        CString* event_log_text) {
  ASSERT1(event_log_text);
  ASSERT1(ping_app_request_data);

  PingEvent::Types event_type = is_update_ ?
                                PingEvent::EVENT_UPDATE_COMPLETE :
                                PingEvent::EVENT_INSTALL_COMPLETE;
  PingEvent ping_event(event_type,
                       PingEvent::EVENT_RESULT_ERROR,
                       GOOPDATE_E_NO_SERVER_RESPONSE,
                       0,  // extra code 1
                       app_data.previous_version());
  ping_app_request_data->AddPingEvent(ping_event);

  event_log_text->AppendFormat(
      _T("App=%s, Ver=%s, Status=no-response-received\n"),
      GuidToString(app_data.app_guid()),
      app_data.version());
}

void JobCreator::HandleUpdateIsAvailable(
    const AppData& app_data,
    const UpdateResponseData& response_data,
    AppRequestData* ping_app_request_data,
    CString* event_log_text,
    Job** job) {
  ASSERT1(ping_app_request_data);
  ASSERT1(event_log_text);
  ASSERT1(job);
  ASSERT1(!app_data.is_update_disabled());

  if (is_auto_update_) {
    if (::IsEqualGUID(kGoopdateGuid, app_data.app_guid())) {
      ++metric_worker_self_updates_available;
    } else {
      ++metric_worker_app_updates_available;
    }

    // Only record an update available event for updates.
    // We have other mechanisms, including IID, to track install success.
    AppManager app_manager(is_machine_);
    app_manager.UpdateUpdateAvailableStats(app_data.parent_app_guid(),
                                           app_data.app_guid());
  }

  // Ping and record events only for "real" jobs. On demand update checks only
  // jobs should not ping, since no update is actually applied.
  if (!is_update_check_only_) {
    PingEvent::Types event_type = is_update_ ?
                                  PingEvent::EVENT_UPDATE_APPLICATION_BEGIN :
                                  PingEvent::EVENT_INSTALL_APPLICATION_BEGIN;
    PingEvent ping_event(event_type,
                         PingEvent::EVENT_RESULT_SUCCESS,
                         0,  // error code
                         0,  // extra code 1
                         app_data.previous_version());
    ping_app_request_data->AddPingEvent(ping_event);
  }
  const TCHAR* status = is_update_check_only_ ? _T("check only") :
                        is_update_ ? _T("update") : _T("install");
  event_log_text->AppendFormat(_T("App=%s, Ver=%s, Status=%s\n"),
                               GuidToString(app_data.app_guid()),
                               app_data.version(),
                               status);

  // TODO(omaha): When components are implemented, how do we handle the case
  // that this is just a place holder and does not really need an update?
  // We may be in an app that only needs an update here because it's child
  // components need updates so we'll need to flag the job of that somehow.
  // Unless it's already tagged in the response_data (which does know that
  // there's nothing to download) but the job state will need to be updated.
  scoped_ptr<Job> new_job(new Job(is_update_, ping_));
  new_job->set_app_data(app_data);
  new_job->set_update_response_data(response_data);
  new_job->set_is_background(is_auto_update_);
  new_job->set_is_update_check_only(is_update_check_only_);

  *job = new_job.release();
}

HRESULT JobCreator::HandleUpdateNotAvailable(
    const AppData& app_data,
    const UpdateResponseData& response_data,
    AppRequestData* ping_app_request_data,
    CString* event_log_text,
    CompletionInfo* completion_info) {
  ASSERT1(ping_app_request_data);
  ASSERT1(event_log_text);
  ASSERT1(completion_info);

  PingEvent::Results result_type = PingEvent::EVENT_RESULT_ERROR;
  CompletionInfo info = UpdateResponseDataToCompletionInfo(
      response_data,
      ping_app_request_data->app_data().display_name());
  switch (info.error_code) {
    case static_cast<DWORD>(GOOPDATE_E_NO_UPDATE_RESPONSE):
      event_log_text->AppendFormat(
          _T("App=%s, Ver=%s, Status=no-update\n"),
          GuidToString(app_data.app_guid()),
          app_data.version());
      if (is_update_) {
        // In case of updates, a "noupdate" response is not an error.
        result_type = PingEvent::EVENT_RESULT_NOUPDATE;
        info.status = COMPLETION_SUCCESS;
        info.error_code = NOERROR;

        AppManager app_manager(is_machine_);
        app_manager.ClearUpdateAvailableStats(app_data.parent_app_guid(),
                                              app_data.app_guid());
        app_manager.RecordSuccessfulUpdateCheck(app_data.parent_app_guid(),
                                                app_data.app_guid());
      }
      break;
    case static_cast<DWORD>(GOOPDATE_E_RESTRICTED_SERVER_RESPONSE):
      event_log_text->AppendFormat(
          _T("App=%s, Ver=%s, Status=restricted\n"),
          GuidToString(app_data.app_guid()),
          app_data.version());
      break;
    case GOOPDATE_E_UNKNOWN_APP_SERVER_RESPONSE:
    case GOOPDATE_E_INTERNAL_ERROR_SERVER_RESPONSE:
    case GOOPDATE_E_SERVER_RESPONSE_NO_HASH:
    case GOOPDATE_E_SERVER_RESPONSE_UNSUPPORTED_PROTOCOL:
    case GOOPDATE_E_UNKNOWN_SERVER_RESPONSE:
    default:
      event_log_text->AppendFormat(_T("App=%s, Ver=%s, Status=error:0x%08x\n"),
                                   GuidToString(app_data.app_guid()),
                                   app_data.version(),
                                   info.error_code);
      break;
  }

  // Only ping for server responses other than "noupdate" or errors.
  if (result_type != PingEvent::EVENT_RESULT_NOUPDATE ||
      info.error_code != NOERROR) {
    PingEvent::Types event_type = is_update_ ?
                                  PingEvent::EVENT_UPDATE_COMPLETE :
                                  PingEvent::EVENT_INSTALL_COMPLETE;
    PingEvent ping_event(event_type,
                         result_type,
                         info.error_code,
                         0,  // extra code 1
                         app_data.previous_version());
    ping_app_request_data->AddPingEvent(ping_event);
  }

  if (fail_if_update_not_available_) {
    *completion_info = info;
    return info.error_code;
  }

  return S_OK;
}

// app_name in UpdateResponseData is not filled in. See the TODO in that class.
CompletionInfo JobCreator::UpdateResponseDataToCompletionInfo(
    const UpdateResponseData& response_data,
    const CString& display_name) {
  CompletionInfo info;
  const CString& status = response_data.status();
  if (_tcsicmp(kResponseStatusOkValue, status) == 0) {
    info.status = COMPLETION_SUCCESS;
    info.error_code = 0;
  } else if (_tcsicmp(kResponseStatusNoUpdate, status) == 0) {
    // "noupdate" is considered an error but the calling code can map it to
    // a successful completion, in the cases of silent and on demand updates.
    info.status = COMPLETION_ERROR;
    info.error_code = static_cast<DWORD>(GOOPDATE_E_NO_UPDATE_RESPONSE);
    VERIFY1(info.text.LoadString(IDS_NO_UPDATE_RESPONSE));
  } else if (_tcsicmp(kResponseStatusRestrictedExportCountry, status) == 0) {
    // "restricted"
    info.status = COMPLETION_ERROR;
    info.error_code =
        static_cast<DWORD>(GOOPDATE_E_RESTRICTED_SERVER_RESPONSE);
    VERIFY1(info.text.LoadString(IDS_RESTRICTED_RESPONSE_FROM_SERVER));
  } else if (_tcsicmp(kResponseStatusUnKnownApplication, status) == 0) {
    // "error-UnKnownApplication"
    info.status = COMPLETION_ERROR;
    info.error_code =
        static_cast<DWORD>(GOOPDATE_E_UNKNOWN_APP_SERVER_RESPONSE);
    VERIFY1(info.text.LoadString(IDS_UNKNOWN_APPLICATION));
  } else if (_tcsicmp(kResponseStatusOsNotSupported, status) == 0) {
    // "error-OsNotSupported"
    info.status = COMPLETION_ERROR;
    info.error_code = static_cast<DWORD>(GOOPDATE_E_OS_NOT_SUPPORTED);
    if (response_data.error_url().IsEmpty()) {
      info.text.FormatMessage(IDS_NON_OK_RESPONSE_FROM_SERVER, status);
    } else {
      info.text.FormatMessage(IDS_OS_NOT_SUPPORTED,
                              display_name,
                              response_data.error_url());
    }
  } else if (_tcsicmp(kResponseStatusInternalError, status) == 0) {
    // "error-internal"
    info.status = COMPLETION_ERROR;
    info.error_code =
        static_cast<DWORD>(GOOPDATE_E_INTERNAL_ERROR_SERVER_RESPONSE);
    info.text.FormatMessage(IDS_NON_OK_RESPONSE_FROM_SERVER, status);
  } else if (_tcsicmp(kResponseStatusHashError, status) == 0) {
    // "error-hash"
    info.status = COMPLETION_ERROR;
    info.error_code =
        static_cast<DWORD>(GOOPDATE_E_SERVER_RESPONSE_NO_HASH);
    info.text.FormatMessage(IDS_NON_OK_RESPONSE_FROM_SERVER, status);
  } else if (_tcsicmp(kResponseStatusUnsupportedProtocol, status) == 0) {
    // "error-unsupportedprotocol"
    info.status = COMPLETION_ERROR;
    info.error_code =
        static_cast<DWORD>(GOOPDATE_E_SERVER_RESPONSE_UNSUPPORTED_PROTOCOL);
    // TODO(omaha): Ideally, we would provide an app-specific URL instead of
    // just the publisher name. If it was a link, we could use point to a
    // redirect URL and provide the app GUID rather than somehow obtaining the
    // app-specific URL.
    info.text.FormatMessage(IDS_INSTALLER_OLD, kPublisherName);
  } else {
    // Unknown response.
    info.status = COMPLETION_ERROR;
    info.error_code =
        static_cast<DWORD>(GOOPDATE_E_UNKNOWN_SERVER_RESPONSE);
    info.text.FormatMessage(IDS_NON_OK_RESPONSE_FROM_SERVER, status);
  }

  return info;
}

bool JobCreator::IsUpdateAvailable(const UpdateResponseData& response_data) {
  return _tcsicmp(kResponseStatusOkValue, response_data.status()) == 0;
}

// Check response and all of its children to see if any of them are in a state
// that requires an update job to be created.
bool JobCreator::IsUpdateAvailable(const UpdateResponse& response) {
  // If the top level response needs updating, short circuit here.
  if (IsUpdateAvailable(response.update_response_data())) {
    return true;
  }

  UpdateResponseDatas::const_iterator it;
  for (it = response.components_begin();
       it != response.components_begin();
       ++it) {
    if (IsUpdateAvailable(it->second)) {
      return true;
    }
  }

  return false;
}

}  // namespace omaha

