/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * 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 <inttypes.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include "perfetto_base/logging.h"
#include "perfetto_base/test/test_task_runner.h"
#include "tracing/core/data_source_config.h"
#include "tracing/core/data_source_descriptor.h"
#include "tracing/core/producer.h"
#include "tracing/core/service.h"
#include "tracing/ipc/producer_ipc_client.h"
#include "tracing/ipc/service_ipc_host.h"
#include "tracing/src/core/service_impl.h"
#include "tracing/src/ipc/posix_shared_memory.h"
#include "tracing/src/ipc/producer/producer_ipc_client_impl.h"
#include "tracing/src/ipc/service/service_ipc_host_impl.h"

namespace perfetto {

namespace {

const char kSocketName[] = "/tmp/perfetto-ipc-test.sock";

class TestProducer : public Producer {
 public:
  void OnConnect() override {
    PERFETTO_DLOG("Connected as Producer");
    if (on_connect)
      on_connect();
  }

  void OnDisconnect() override {
    PERFETTO_DLOG("Disconnected from tracing service");
  }

  void CreateDataSourceInstance(DataSourceInstanceID dsid,
                                const DataSourceConfig& cfg) override {
    PERFETTO_DLOG(
        "The tracing service requested us to start a new data source %" PRIu64
        ", config: %s",
        dsid, cfg.trace_category_filters.c_str());
  }

  void TearDownDataSourceInstance(DataSourceInstanceID instance_id) override {
    PERFETTO_DLOG(
        "The tracing service requested us to shutdown the data source %" PRIu64,
        instance_id);
  }

  std::function<void()> on_connect;
};

void __attribute__((noreturn)) ProducerMain() {
  base::TestTaskRunner task_runner;
  TestProducer producer;
  std::unique_ptr<Service::ProducerEndpoint> endpoint =
      ProducerIPCClient::Connect(kSocketName, &producer, &task_runner);
  producer.on_connect = task_runner.CreateCheckpoint("connect");
  task_runner.RunUntilCheckpoint("connect");

  for (int i = 0; i < 3; i++) {
    DataSourceDescriptor descriptor;
    descriptor.name = "perfetto.test.data_source";
    auto reg_checkpoint =
        task_runner.CreateCheckpoint("register" + std::to_string(i));
    auto on_register = [reg_checkpoint](DataSourceID id) {
      printf("Service acked RegisterDataSource() with ID %" PRIu64 "\n", id);
      reg_checkpoint();
    };
    endpoint->RegisterDataSource(descriptor, on_register);
    task_runner.RunUntilCheckpoint("register" + std::to_string(i));

    auto* ipc_client = static_cast<ProducerIPCClientImpl*>(endpoint.get());
    void* shm = ipc_client->shared_memory()->start();
    char buf[32];
    memcpy(buf, shm, sizeof(buf));
    buf[sizeof(buf) - 1] = '\0';
    printf("Shared Memory contents: \"%s\"\n", buf);
  }
  task_runner.Run();
}

void __attribute__((noreturn)) ServiceMain() {
  unlink(kSocketName);
  base::TestTaskRunner task_runner;
  std::unique_ptr<ServiceIPCHostImpl> host(static_cast<ServiceIPCHostImpl*>(
      ServiceIPCHost::CreateInstance(&task_runner).release()));

  class Observer : public Service::ObserverForTesting {
   public:
    explicit Observer(ServiceImpl* svc) : svc_(svc) {}
    void OnProducerConnected(ProducerID prid) override {
      printf("Producer connected: ID=%" PRIu64 "\n", prid);
    }

    void OnProducerDisconnected(ProducerID prid) override {
      printf("Producer disconnected: ID=%" PRIu64 "\n", prid);
    }

    void OnDataSourceRegistered(ProducerID prid, DataSourceID dsid) override {
      printf("Data source registered, Producer=%" PRIu64 " DataSource=%" PRIu64
             "\n",
             prid, dsid);
      DataSourceConfig cfg;
      cfg.trace_category_filters = "foo,bar";
      SharedMemory* shm = svc_->GetProducer(prid)->shared_memory();
      char shm_contents[32];
      sprintf(shm_contents, "shmem @ iteration %" PRIu64, dsid);
      memcpy(shm->start(), shm_contents, sizeof(shm_contents));
      svc_->GetProducer(prid)->producer()->CreateDataSourceInstance(42, cfg);
    }

    void OnDataSourceUnregistered(ProducerID prid, DataSourceID dsid) override {
      printf("Data source unregistered, Producer=%" PRIu64
             " DataSource=%" PRIu64 "\n",
             prid, dsid);
    }

    ServiceImpl* svc_;
  };

  host->Start(kSocketName);
  Observer observer(static_cast<ServiceImpl*>(host->service_for_testing()));
  host->service_for_testing()->set_observer_for_testing(&observer);
  task_runner.Run();
}

}  // namespace.
}  // namespace perfetto

int main(int argc, char** argv) {
  if (argc == 2 && !strcmp(argv[1], "producer"))
    perfetto::ProducerMain();
  if (argc == 2 && !strcmp(argv[1], "service"))
    perfetto::ServiceMain();

  fprintf(stderr, "Usage: %s producer | service\n", argv[0]);
  return 1;
}
