// Copyright 2018 The Cobalt Authors. All Rights Reserved.
//
// 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 "starboard/shared/uwp/log_writer_uwp.h"

#include <string>

#include "starboard/common/log.h"
#include "starboard/common/mutex.h"
#include "starboard/common/semaphore.h"
#include "starboard/common/string.h"
#include "starboard/once.h"
#include "starboard/shared/win32/wchar_utils.h"

using Windows::Foundation::AsyncOperationCompletedHandler;
using Windows::Foundation::AsyncStatus;
using Windows::Foundation::IAsyncOperation;
using Windows::Storage::FileAccessMode;
using Windows::Storage::StorageFile;
using Windows::Storage::StorageFolder;
using Windows::Storage::Streams::DataWriter;
using Windows::Storage::Streams::IOutputStream;
using Windows::Storage::Streams::IRandomAccessStream;

namespace starboard {
namespace shared {
namespace uwp {
namespace {

class SharedMutex {
 public:
  SharedMutex() : sema_(1) {}
  void Acquire() { sema_.Take(); }
  void Release() { sema_.Put(); }
  bool AcquireTry() { return sema_.TakeTry(); }

 private:
  Semaphore sema_;
};

class LogWriterUWP : public ILogWriter {
 public:
  LogWriterUWP(StorageFolder ^ folder, const char* filename) {
    OpenLogFile(folder, filename);
  }

  ~LogWriterUWP() { CloseLogFile(); }

  void Write(const char* content, int size) override {
    WriteToLogFile(content, size);
  }

 private:
  // SbMutex is not reentrant, so factor out close log file functionality for
  // use by other functions.
  void CloseLogFile_Locked() { log_writer_ = nullptr; }

  void CloseLogFile() {
    log_mutex_.Acquire();
    CloseLogFile_Locked();
    log_mutex_.Release();
  }

  void OpenLogFile(StorageFolder ^ folder, const char* filename) {
    std::wstring wfilename = win32::CStringToWString(filename);

    log_mutex_.Acquire();
    CloseLogFile_Locked();

    // Manually set the completion callback function instead of using
    // concurrency::create_task() since those tasks may not execute before the
    // UI thread wants the log_mutex_ to output another log.
    auto task = folder->CreateFileAsync(
        ref new Platform::String(wfilename.c_str()),
        Windows::Storage::CreationCollisionOption::ReplaceExisting);
    task->Completed = ref new AsyncOperationCompletedHandler<StorageFile ^>(
        [folder, this](IAsyncOperation<StorageFile ^> ^ op, AsyncStatus) {
          if (op->Status != AsyncStatus::Completed) {
            this->log_mutex_.Release();
            SB_LOG(ERROR) << "Unable to open log file in folder "
                          << win32::platformStringToString(folder->Name);
            return;
          }

          try {
            auto task = op->GetResults()->OpenAsync(FileAccessMode::ReadWrite);
            task->Completed =
                ref new AsyncOperationCompletedHandler<IRandomAccessStream ^>(
                    [this](IAsyncOperation<IRandomAccessStream ^> ^ op,
                           AsyncStatus) {
                      this->log_writer_ = ref new DataWriter(
                          op->GetResults()->GetOutputStreamAt(0));
                      this->log_mutex_.Release();
                    });
          } catch (Platform::Exception ^) {
            this->log_mutex_.Release();
            SB_LOG(ERROR) << "Unable to open log file in folder "
                          << win32::platformStringToString(folder->Name);
          }
        });
  }

  void WriteToLogFile(const char* text, int text_length) {
    if (text_length <= 0) {
      return;
    }
    log_mutex_.Acquire();
    if (log_writer_) {
      log_writer_->WriteBytes(ref new Platform::Array<unsigned char>(
          (unsigned char*)text, text_length));

      // Manually set the completion callback function instead of using
      // concurrency::create_task() since those tasks may not execute before the
      // UI thread wants the log_mutex_ to output another log.
      auto task = log_writer_->StoreAsync();
      task->Completed = ref new AsyncOperationCompletedHandler<unsigned int>(
          [this](IAsyncOperation<unsigned int> ^, AsyncStatus) {
            auto task = this->log_writer_->FlushAsync();
            task->Completed = ref new AsyncOperationCompletedHandler<bool>(
                [this](IAsyncOperation<bool> ^, AsyncStatus) {
                  this->log_mutex_.Release();
                });
          });
    } else {
      log_mutex_.Release();
    }
  }
  SharedMutex log_mutex_;
  // The Windows Storage API must be used in order to access files in
  // privileged areas (e.g. KnownFolders::RemovableDevices). The win32
  // file API used by SbFile returns access denied errors in these situations.
  DataWriter ^ log_writer_ = nullptr;
};
}  // namespace.

scoped_ptr<ILogWriter> CreateLogWriterUWP(Windows::Storage::StorageFolder ^
                                              folder,
                                          const char* filename) {
  scoped_ptr<ILogWriter> output(new LogWriterUWP(folder, filename));
  return output.Pass();
}

}  // namespace uwp
}  // namespace shared
}  // namespace starboard
