/*
 * Copyright 2017, OpenCensus Authors
 *
 * 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.
 */

package io.opencensus.exporter.stats.stackdriver;

import static com.google.common.base.Preconditions.checkArgument;

import com.google.api.Distribution;
import com.google.api.Distribution.BucketOptions;
import com.google.api.Distribution.BucketOptions.Explicit;
import com.google.api.LabelDescriptor;
import com.google.api.LabelDescriptor.ValueType;
import com.google.api.Metric;
import com.google.api.MetricDescriptor;
import com.google.api.MetricDescriptor.MetricKind;
import com.google.api.MonitoredResource;
import com.google.cloud.MetadataConfig;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.monitoring.v3.Point;
import com.google.monitoring.v3.TimeInterval;
import com.google.monitoring.v3.TimeSeries;
import com.google.monitoring.v3.TypedValue;
import com.google.monitoring.v3.TypedValue.Builder;
import com.google.protobuf.Timestamp;
import io.opencensus.common.Function;
import io.opencensus.common.Functions;
import io.opencensus.contrib.monitoredresource.util.MonitoredResource.AwsEc2InstanceMonitoredResource;
import io.opencensus.contrib.monitoredresource.util.MonitoredResource.GcpGceInstanceMonitoredResource;
import io.opencensus.contrib.monitoredresource.util.MonitoredResource.GcpGkeContainerMonitoredResource;
import io.opencensus.contrib.monitoredresource.util.MonitoredResourceUtils;
import io.opencensus.contrib.monitoredresource.util.ResourceType;
import io.opencensus.stats.Aggregation;
import io.opencensus.stats.Aggregation.LastValue;
import io.opencensus.stats.AggregationData;
import io.opencensus.stats.AggregationData.CountData;
import io.opencensus.stats.AggregationData.DistributionData;
import io.opencensus.stats.AggregationData.LastValueDataDouble;
import io.opencensus.stats.AggregationData.LastValueDataLong;
import io.opencensus.stats.AggregationData.SumDataDouble;
import io.opencensus.stats.AggregationData.SumDataLong;
import io.opencensus.stats.BucketBoundaries;
import io.opencensus.stats.Measure;
import io.opencensus.stats.View;
import io.opencensus.stats.ViewData;
import io.opencensus.tags.TagKey;
import io.opencensus.tags.TagValue;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.SecureRandom;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;

/*>>>
import org.checkerframework.checker.nullness.qual.Nullable;
*/

/** Util methods to convert OpenCensus Stats data models to StackDriver monitoring data models. */
@SuppressWarnings("deprecation")
final class StackdriverExportUtils {

  // TODO(songya): do we want these constants to be customizable?
  @VisibleForTesting static final String LABEL_DESCRIPTION = "OpenCensus TagKey";
  @VisibleForTesting static final String OPENCENSUS_TASK = "opencensus_task";
  @VisibleForTesting static final String OPENCENSUS_TASK_DESCRIPTION = "Opencensus task identifier";
  private static final String GCP_GKE_CONTAINER = "k8s_container";
  private static final String GCP_GCE_INSTANCE = "gce_instance";
  private static final String AWS_EC2_INSTANCE = "aws_ec2_instance";
  private static final String GLOBAL = "global";

  private static final Logger logger = Logger.getLogger(StackdriverExportUtils.class.getName());
  private static final String OPENCENSUS_TASK_VALUE_DEFAULT = generateDefaultTaskValue();
  private static final String PROJECT_ID_LABEL_KEY = "project_id";

  // Constant functions for ValueType.
  private static final Function<Object, MetricDescriptor.ValueType> VALUE_TYPE_DOUBLE_FUNCTION =
      Functions.returnConstant(MetricDescriptor.ValueType.DOUBLE);
  private static final Function<Object, MetricDescriptor.ValueType> VALUE_TYPE_INT64_FUNCTION =
      Functions.returnConstant(MetricDescriptor.ValueType.INT64);
  private static final Function<Object, MetricDescriptor.ValueType>
      VALUE_TYPE_UNRECOGNIZED_FUNCTION =
          Functions.returnConstant(MetricDescriptor.ValueType.UNRECOGNIZED);
  private static final Function<Object, MetricDescriptor.ValueType>
      VALUE_TYPE_DISTRIBUTION_FUNCTION =
          Functions.returnConstant(MetricDescriptor.ValueType.DISTRIBUTION);
  private static final Function<Aggregation, MetricDescriptor.ValueType> valueTypeMeanFunction =
      new Function<Aggregation, MetricDescriptor.ValueType>() {
        @Override
        public MetricDescriptor.ValueType apply(Aggregation arg) {
          // TODO(songya): remove this once Mean aggregation is completely removed. Before that
          // we need to continue supporting Mean, since it could still be used by users and some
          // deprecated RPC views.
          if (arg instanceof Aggregation.Mean) {
            return MetricDescriptor.ValueType.DOUBLE;
          }
          return MetricDescriptor.ValueType.UNRECOGNIZED;
        }
      };

  // Constant functions for MetricKind.
  private static final Function<Object, MetricKind> METRIC_KIND_CUMULATIVE_FUNCTION =
      Functions.returnConstant(MetricKind.CUMULATIVE);
  private static final Function<Object, MetricKind> METRIC_KIND_UNRECOGNIZED_FUNCTION =
      Functions.returnConstant(MetricKind.UNRECOGNIZED);

  // Constant functions for TypedValue.
  private static final Function<SumDataDouble, TypedValue> typedValueSumDoubleFunction =
      new Function<SumDataDouble, TypedValue>() {
        @Override
        public TypedValue apply(SumDataDouble arg) {
          Builder builder = TypedValue.newBuilder();
          builder.setDoubleValue(arg.getSum());
          return builder.build();
        }
      };
  private static final Function<SumDataLong, TypedValue> typedValueSumLongFunction =
      new Function<SumDataLong, TypedValue>() {
        @Override
        public TypedValue apply(SumDataLong arg) {
          Builder builder = TypedValue.newBuilder();
          builder.setInt64Value(arg.getSum());
          return builder.build();
        }
      };
  private static final Function<CountData, TypedValue> typedValueCountFunction =
      new Function<CountData, TypedValue>() {
        @Override
        public TypedValue apply(CountData arg) {
          Builder builder = TypedValue.newBuilder();
          builder.setInt64Value(arg.getCount());
          return builder.build();
        }
      };
  private static final Function<LastValueDataDouble, TypedValue> typedValueLastValueDoubleFunction =
      new Function<LastValueDataDouble, TypedValue>() {
        @Override
        public TypedValue apply(LastValueDataDouble arg) {
          Builder builder = TypedValue.newBuilder();
          builder.setDoubleValue(arg.getLastValue());
          return builder.build();
        }
      };
  private static final Function<LastValueDataLong, TypedValue> typedValueLastValueLongFunction =
      new Function<LastValueDataLong, TypedValue>() {
        @Override
        public TypedValue apply(LastValueDataLong arg) {
          Builder builder = TypedValue.newBuilder();
          builder.setInt64Value(arg.getLastValue());
          return builder.build();
        }
      };
  private static final Function<AggregationData, TypedValue> typedValueMeanFunction =
      new Function<AggregationData, TypedValue>() {
        @Override
        public TypedValue apply(AggregationData arg) {
          Builder builder = TypedValue.newBuilder();
          // TODO(songya): remove this once Mean aggregation is completely removed. Before that
          // we need to continue supporting Mean, since it could still be used by users and some
          // deprecated RPC views.
          if (arg instanceof AggregationData.MeanData) {
            builder.setDoubleValue(((AggregationData.MeanData) arg).getMean());
            return builder.build();
          }
          throw new IllegalArgumentException("Unknown Aggregation");
        }
      };

  private static String generateDefaultTaskValue() {
    // Something like '<pid>@<hostname>', at least in Oracle and OpenJdk JVMs
    final String jvmName = ManagementFactory.getRuntimeMXBean().getName();
    // If not the expected format then generate a random number.
    if (jvmName.indexOf('@') < 1) {
      String hostname = "localhost";
      try {
        hostname = InetAddress.getLocalHost().getHostName();
      } catch (UnknownHostException e) {
        logger.log(Level.INFO, "Unable to get the hostname.", e);
      }
      // Generate a random number and use the same format "random_number@hostname".
      return "java-" + new SecureRandom().nextInt() + "@" + hostname;
    }
    return "java-" + jvmName;
  }

  // Construct a MetricDescriptor using a View.
  @javax.annotation.Nullable
  static MetricDescriptor createMetricDescriptor(
      View view, String projectId, String domain, String displayNamePrefix) {
    if (!(view.getWindow() instanceof View.AggregationWindow.Cumulative)) {
      // TODO(songya): Only Cumulative view will be exported to Stackdriver in this version.
      return null;
    }

    MetricDescriptor.Builder builder = MetricDescriptor.newBuilder();
    String viewName = view.getName().asString();
    String type = generateType(viewName, domain);
    // Name format refers to
    // cloud.google.com/monitoring/api/ref_v3/rest/v3/projects.metricDescriptors/create
    builder.setName(String.format("projects/%s/metricDescriptors/%s", projectId, type));
    builder.setType(type);
    builder.setDescription(view.getDescription());
    String displayName = createDisplayName(viewName, displayNamePrefix);
    builder.setDisplayName(displayName);
    for (TagKey tagKey : view.getColumns()) {
      builder.addLabels(createLabelDescriptor(tagKey));
    }
    builder.addLabels(
        LabelDescriptor.newBuilder()
            .setKey(OPENCENSUS_TASK)
            .setDescription(OPENCENSUS_TASK_DESCRIPTION)
            .setValueType(ValueType.STRING)
            .build());
    builder.setUnit(createUnit(view.getAggregation(), view.getMeasure()));
    builder.setMetricKind(createMetricKind(view.getWindow(), view.getAggregation()));
    builder.setValueType(createValueType(view.getAggregation(), view.getMeasure()));
    return builder.build();
  }

  private static String generateType(String viewName, String domain) {
    return domain + viewName;
  }

  private static String createDisplayName(String viewName, String displayNamePrefix) {
    return displayNamePrefix + viewName;
  }

  // Construct a LabelDescriptor from a TagKey
  @VisibleForTesting
  static LabelDescriptor createLabelDescriptor(TagKey tagKey) {
    LabelDescriptor.Builder builder = LabelDescriptor.newBuilder();
    builder.setKey(tagKey.getName());
    builder.setDescription(LABEL_DESCRIPTION);
    // Now we only support String tags
    builder.setValueType(ValueType.STRING);
    return builder.build();
  }

  // Construct a MetricKind from an AggregationWindow
  @VisibleForTesting
  static MetricKind createMetricKind(View.AggregationWindow window, Aggregation aggregation) {
    if (aggregation instanceof LastValue) {
      return MetricKind.GAUGE;
    }
    return window.match(
        METRIC_KIND_CUMULATIVE_FUNCTION, // Cumulative
        // TODO(songya): We don't support exporting Interval stats to StackDriver in this version.
        METRIC_KIND_UNRECOGNIZED_FUNCTION, // Interval
        METRIC_KIND_UNRECOGNIZED_FUNCTION);
  }

  // Construct a MetricDescriptor.ValueType from an Aggregation and a Measure
  @VisibleForTesting
  static String createUnit(Aggregation aggregation, final Measure measure) {
    if (aggregation instanceof Aggregation.Count) {
      return "1";
    }
    return measure.getUnit();
  }

  // Construct a MetricDescriptor.ValueType from an Aggregation and a Measure
  @VisibleForTesting
  static MetricDescriptor.ValueType createValueType(
      Aggregation aggregation, final Measure measure) {
    return aggregation.match(
        Functions.returnConstant(
            measure.match(
                VALUE_TYPE_DOUBLE_FUNCTION, // Sum Double
                VALUE_TYPE_INT64_FUNCTION, // Sum Long
                VALUE_TYPE_UNRECOGNIZED_FUNCTION)),
        VALUE_TYPE_INT64_FUNCTION, // Count
        VALUE_TYPE_DISTRIBUTION_FUNCTION, // Distribution
        Functions.returnConstant(
            measure.match(
                VALUE_TYPE_DOUBLE_FUNCTION, // LastValue Double
                VALUE_TYPE_INT64_FUNCTION, // LastValue Long
                VALUE_TYPE_UNRECOGNIZED_FUNCTION)),
        valueTypeMeanFunction);
  }

  // Convert ViewData to a list of TimeSeries, so that ViewData can be uploaded to Stackdriver.
  static List<TimeSeries> createTimeSeriesList(
      @javax.annotation.Nullable ViewData viewData,
      MonitoredResource monitoredResource,
      String domain) {
    List<TimeSeries> timeSeriesList = Lists.newArrayList();
    if (viewData == null) {
      return timeSeriesList;
    }
    View view = viewData.getView();
    if (!(view.getWindow() instanceof View.AggregationWindow.Cumulative)) {
      // TODO(songya): Only Cumulative view will be exported to Stackdriver in this version.
      return timeSeriesList;
    }

    // Shared fields for all TimeSeries generated from the same ViewData
    TimeSeries.Builder shared = TimeSeries.newBuilder();
    shared.setMetricKind(createMetricKind(view.getWindow(), view.getAggregation()));
    shared.setResource(monitoredResource);
    shared.setValueType(createValueType(view.getAggregation(), view.getMeasure()));

    // Each entry in AggregationMap will be converted into an independent TimeSeries object
    for (Entry<List</*@Nullable*/ TagValue>, AggregationData> entry :
        viewData.getAggregationMap().entrySet()) {
      TimeSeries.Builder builder = shared.clone();
      builder.setMetric(createMetric(view, entry.getKey(), domain));
      builder.addPoints(
          createPoint(entry.getValue(), viewData.getWindowData(), view.getAggregation()));
      timeSeriesList.add(builder.build());
    }

    return timeSeriesList;
  }

  // Create a Metric using the TagKeys and TagValues.
  @VisibleForTesting
  static Metric createMetric(View view, List</*@Nullable*/ TagValue> tagValues, String domain) {
    Metric.Builder builder = Metric.newBuilder();
    // TODO(songya): use pre-defined metrics for canonical views
    builder.setType(generateType(view.getName().asString(), domain));
    Map<String, String> stringTagMap = Maps.newHashMap();
    List<TagKey> columns = view.getColumns();
    checkArgument(
        tagValues.size() == columns.size(), "TagKeys and TagValues don't have same size.");
    for (int i = 0; i < tagValues.size(); i++) {
      TagKey key = columns.get(i);
      TagValue value = tagValues.get(i);
      if (value == null) {
        continue;
      }
      stringTagMap.put(key.getName(), value.asString());
    }
    stringTagMap.put(OPENCENSUS_TASK, OPENCENSUS_TASK_VALUE_DEFAULT);
    builder.putAllLabels(stringTagMap);
    return builder.build();
  }

  // Create Point from AggregationData, AggregationWindowData and Aggregation.
  @VisibleForTesting
  static Point createPoint(
      AggregationData aggregationData,
      ViewData.AggregationWindowData windowData,
      Aggregation aggregation) {
    Point.Builder builder = Point.newBuilder();
    builder.setInterval(createTimeInterval(windowData, aggregation));
    builder.setValue(createTypedValue(aggregation, aggregationData));
    return builder.build();
  }

  // Convert AggregationWindowData to TimeInterval, currently only support CumulativeData.
  @VisibleForTesting
  static TimeInterval createTimeInterval(
      ViewData.AggregationWindowData windowData, final Aggregation aggregation) {
    return windowData.match(
        new Function<ViewData.AggregationWindowData.CumulativeData, TimeInterval>() {
          @Override
          public TimeInterval apply(ViewData.AggregationWindowData.CumulativeData arg) {
            TimeInterval.Builder builder = TimeInterval.newBuilder();
            builder.setEndTime(convertTimestamp(arg.getEnd()));
            if (!(aggregation instanceof LastValue)) {
              builder.setStartTime(convertTimestamp(arg.getStart()));
            }
            return builder.build();
          }
        },
        Functions.<TimeInterval>throwIllegalArgumentException(),
        Functions.<TimeInterval>throwIllegalArgumentException());
  }

  // Create a TypedValue using AggregationData and Aggregation
  // Note TypedValue is "A single strongly-typed value", i.e only one field should be set.
  @VisibleForTesting
  static TypedValue createTypedValue(
      final Aggregation aggregation, AggregationData aggregationData) {
    return aggregationData.match(
        typedValueSumDoubleFunction,
        typedValueSumLongFunction,
        typedValueCountFunction,
        new Function<DistributionData, TypedValue>() {
          @Override
          public TypedValue apply(DistributionData arg) {
            TypedValue.Builder builder = TypedValue.newBuilder();
            checkArgument(
                aggregation instanceof Aggregation.Distribution,
                "Aggregation and AggregationData mismatch.");
            builder.setDistributionValue(
                createDistribution(
                    arg, ((Aggregation.Distribution) aggregation).getBucketBoundaries()));
            return builder.build();
          }
        },
        typedValueLastValueDoubleFunction,
        typedValueLastValueLongFunction,
        typedValueMeanFunction);
  }

  // Create a StackDriver Distribution from DistributionData and BucketBoundaries
  @VisibleForTesting
  static Distribution createDistribution(
      DistributionData distributionData, BucketBoundaries bucketBoundaries) {
    return Distribution.newBuilder()
        .setBucketOptions(createBucketOptions(bucketBoundaries))
        .addAllBucketCounts(distributionData.getBucketCounts())
        .setCount(distributionData.getCount())
        .setMean(distributionData.getMean())
        // TODO(songya): uncomment this once Stackdriver supports setting max and min.
        // .setRange(
        //    Range.newBuilder()
        //        .setMax(distributionData.getMax())
        //        .setMin(distributionData.getMin())
        //        .build())
        .setSumOfSquaredDeviation(distributionData.getSumOfSquaredDeviations())
        .build();
  }

  // Create BucketOptions from BucketBoundaries
  @VisibleForTesting
  static BucketOptions createBucketOptions(BucketBoundaries bucketBoundaries) {
    return BucketOptions.newBuilder()
        .setExplicitBuckets(Explicit.newBuilder().addAllBounds(bucketBoundaries.getBoundaries()))
        .build();
  }

  // Convert a Census Timestamp to a StackDriver Timestamp
  @VisibleForTesting
  static Timestamp convertTimestamp(io.opencensus.common.Timestamp censusTimestamp) {
    if (censusTimestamp.getSeconds() < 0) {
      // Stackdriver doesn't handle negative timestamps.
      return Timestamp.newBuilder().build();
    }
    return Timestamp.newBuilder()
        .setSeconds(censusTimestamp.getSeconds())
        .setNanos(censusTimestamp.getNanos())
        .build();
  }

  /* Return a self-configured Stackdriver monitored resource. */
  static MonitoredResource getDefaultResource() {
    MonitoredResource.Builder builder = MonitoredResource.newBuilder();
    io.opencensus.contrib.monitoredresource.util.MonitoredResource autoDetectedResource =
        MonitoredResourceUtils.getDefaultResource();
    if (autoDetectedResource == null) {
      builder.setType(GLOBAL);
      if (MetadataConfig.getProjectId() != null) {
        // For default global resource, always use the project id from MetadataConfig. This allows
        // stats from other projects (e.g from GAE running in another project) to be collected.
        builder.putLabels(PROJECT_ID_LABEL_KEY, MetadataConfig.getProjectId());
      }
      return builder.build();
    }
    builder.setType(mapToStackdriverResourceType(autoDetectedResource.getResourceType()));
    setMonitoredResourceLabelsForBuilder(builder, autoDetectedResource);
    return builder.build();
  }

  private static String mapToStackdriverResourceType(ResourceType resourceType) {
    switch (resourceType) {
      case GCP_GCE_INSTANCE:
        return GCP_GCE_INSTANCE;
      case GCP_GKE_CONTAINER:
        return GCP_GKE_CONTAINER;
      case AWS_EC2_INSTANCE:
        return AWS_EC2_INSTANCE;
    }
    throw new IllegalArgumentException("Unknown resource type.");
  }

  private static void setMonitoredResourceLabelsForBuilder(
      MonitoredResource.Builder builder,
      io.opencensus.contrib.monitoredresource.util.MonitoredResource autoDetectedResource) {
    switch (autoDetectedResource.getResourceType()) {
      case GCP_GCE_INSTANCE:
        GcpGceInstanceMonitoredResource gcpGceInstanceMonitoredResource =
            (GcpGceInstanceMonitoredResource) autoDetectedResource;
        builder.putLabels(PROJECT_ID_LABEL_KEY, gcpGceInstanceMonitoredResource.getAccount());
        builder.putLabels("instance_id", gcpGceInstanceMonitoredResource.getInstanceId());
        builder.putLabels("zone", gcpGceInstanceMonitoredResource.getZone());
        return;
      case GCP_GKE_CONTAINER:
        GcpGkeContainerMonitoredResource gcpGkeContainerMonitoredResource =
            (GcpGkeContainerMonitoredResource) autoDetectedResource;
        builder.putLabels(PROJECT_ID_LABEL_KEY, gcpGkeContainerMonitoredResource.getAccount());
        builder.putLabels("cluster_name", gcpGkeContainerMonitoredResource.getClusterName());
        builder.putLabels("container_name", gcpGkeContainerMonitoredResource.getContainerName());
        builder.putLabels("namespace_name", gcpGkeContainerMonitoredResource.getNamespaceId());
        builder.putLabels("pod_name", gcpGkeContainerMonitoredResource.getPodId());
        builder.putLabels("location", gcpGkeContainerMonitoredResource.getZone());
        return;
      case AWS_EC2_INSTANCE:
        AwsEc2InstanceMonitoredResource awsEc2InstanceMonitoredResource =
            (AwsEc2InstanceMonitoredResource) autoDetectedResource;
        builder.putLabels("aws_account", awsEc2InstanceMonitoredResource.getAccount());
        builder.putLabels("instance_id", awsEc2InstanceMonitoredResource.getInstanceId());
        builder.putLabels("region", "aws:" + awsEc2InstanceMonitoredResource.getRegion());
        return;
    }
    throw new IllegalArgumentException("Unknown subclass of MonitoredResource.");
  }

  private StackdriverExportUtils() {}
}
