/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.apache.htrace.impl;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import org.apache.htrace.Span;
import org.apache.htrace.TimelineAnnotation;
import org.apache.htrace.Tracer;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * A Span implementation that stores its information in milliseconds since the
 * epoch.
 */
@JsonDeserialize(using = MilliSpan.MilliSpanDeserializer.class)
public class MilliSpan implements Span {
  private static ObjectWriter JSON_WRITER = new ObjectMapper().writer();
  private static final long EMPTY_PARENT_ARRAY[] = new long[0];
  private static final String EMPTY_STRING = "";

  private long begin;
  private long end;
  private final String description;
  private final long traceId;
  private long parents[];
  private final long spanId;
  private Map<String, String> traceInfo = null;
  private String processId;
  private List<TimelineAnnotation> timeline = null;
  private final static Random random = new Random();

  private static long nonZeroRandom64() {
    long id;
    do {
      id = random.nextLong();
    } while (id == 0);
    return id;
  }

  @Override
  public Span child(String childDescription) {
    return new MilliSpan.Builder().
      begin(System.currentTimeMillis()).
      end(0).
      description(childDescription).
      traceId(traceId).
      parents(new long[] {spanId}).
      spanId(nonZeroRandom64()).
      processId(processId).
      build();
  }

  /**
   * The public interface for constructing a MilliSpan.
   */
  public static class Builder {
    private long begin;
    private long end;
    private String description = EMPTY_STRING;
    private long traceId;
    private long parents[] = EMPTY_PARENT_ARRAY;
    private long spanId;
    private Map<String, String> traceInfo = null;
    private String processId = EMPTY_STRING;
    private List<TimelineAnnotation> timeline = null;

    public Builder() {
    }

    public Builder begin(long begin) {
      this.begin = begin;
      return this;
    }

    public Builder end(long end) {
      this.end = end;
      return this;
    }

    public Builder description(String description) {
      this.description = description;
      return this;
    }

    public Builder traceId(long traceId) {
      this.traceId = traceId;
      return this;
    }

    public Builder parents(long parents[]) {
      this.parents = parents;
      return this;
    }

    public Builder parents(List<Long> parentList) {
      long[] parents = new long[parentList.size()];
      for (int i = 0; i < parentList.size(); i++) {
        parents[i] = parentList.get(i).longValue();
      }
      this.parents = parents;
      return this;
    }

    public Builder spanId(long spanId) {
      this.spanId = spanId;
      return this;
    }

    public Builder traceInfo(Map<String, String> traceInfo) {
      this.traceInfo = traceInfo.isEmpty() ? null : traceInfo;
      return this;
    }

    public Builder processId(String processId) {
      this.processId = processId;
      return this;
    }

    public Builder timeline(List<TimelineAnnotation> timeline) {
      this.timeline = timeline.isEmpty() ? null : timeline;
      return this;
    }

    public MilliSpan build() {
      return new MilliSpan(this);
    }
  }

  public MilliSpan() {
    this.begin = 0;
    this.end = 0;
    this.description = EMPTY_STRING;
    this.traceId = 0;
    this.parents = EMPTY_PARENT_ARRAY;
    this.spanId = 0;
    this.traceInfo = null;
    this.processId = EMPTY_STRING;
    this.timeline = null;
  }

  private MilliSpan(Builder builder) {
    this.begin = builder.begin;
    this.end = builder.end;
    this.description = builder.description;
    this.traceId = builder.traceId;
    this.parents = builder.parents;
    this.spanId = builder.spanId;
    this.traceInfo = builder.traceInfo;
    this.processId = builder.processId;
    this.timeline = builder.timeline;
  }

  @Override
  public synchronized void stop() {
    if (end == 0) {
      if (begin == 0)
        throw new IllegalStateException("Span for " + description
            + " has not been started");
      end = System.currentTimeMillis();
      Tracer.getInstance().deliver(this);
    }
  }

  protected long currentTimeMillis() {
    return System.currentTimeMillis();
  }

  @Override
  public synchronized boolean isRunning() {
    return begin != 0 && end == 0;
  }

  @Override
  public synchronized long getAccumulatedMillis() {
    if (begin == 0)
      return 0;
    if (end > 0)
      return end - begin;
    return currentTimeMillis() - begin;
  }

  @Override
  public String toString() {
    return toJson();
  }

  @Override
  public String getDescription() {
    return description;
  }

  @Override
  public long getSpanId() {
    return spanId;
  }

  @Override
  public long[] getParents() {
    return parents;
  }

  @Override
  public void setParents(long[] parents) {
    this.parents = parents;
  }

  @Override
  public long getTraceId() {
    return traceId;
  }

  @Override
  public long getStartTimeMillis() {
    return begin;
  }

  @Override
  public long getStopTimeMillis() {
    return end;
  }

  @Override
  public void addKVAnnotation(byte[] key, byte[] value)  {
    // TODO: remove this method
    try {
      addKVAnnotation(new String(key, "UTF-8"), new String(value, "UTF-8"));
    } catch (UnsupportedEncodingException e) {
      throw new RuntimeException(e);
    }
  }

  @Override
  public void addKVAnnotation(String key, String value) {
    if (traceInfo == null)
      traceInfo = new HashMap<String, String>();
    traceInfo.put(key, value);
  }

  @Override
  public void addTimelineAnnotation(String msg) {
    if (timeline == null) {
      timeline = new ArrayList<TimelineAnnotation>();
    }
    timeline.add(new TimelineAnnotation(System.currentTimeMillis(), msg));
  }

  @Override
  public Map<String, String> getKVAnnotations() {
    if (traceInfo == null)
      return Collections.emptyMap();
    return Collections.unmodifiableMap(traceInfo);
  }

  @Override
  public List<TimelineAnnotation> getTimelineAnnotations() {
    if (timeline == null) {
      return Collections.emptyList();
    }
    return Collections.unmodifiableList(timeline);
  }

  @Override
  public String getProcessId() {
    return processId;
  }

  @Override
  public void setProcessId(String processId) {
    this.processId = processId;
  }

  @Override
  public String toJson() {
    StringWriter writer = new StringWriter();
    try {
      JSON_WRITER.writeValue(writer, this);
    } catch (IOException e) {
      // An IOException should not be possible when writing to a string.
      throw new RuntimeException(e);
    }
    return writer.toString();
  }

  private static long parseUnsignedHexLong(String s) {
    return new BigInteger(s, 16).longValue();
  }

  public static class MilliSpanDeserializer
        extends JsonDeserializer<MilliSpan> {
    @Override
    public MilliSpan deserialize(JsonParser jp, DeserializationContext ctxt)
          throws IOException, JsonProcessingException {
      JsonNode root = jp.getCodec().readTree(jp);
      Builder builder = new Builder();
      JsonNode bNode = root.get("b");
      if (bNode != null) {
        builder.begin(bNode.asLong());
      }
      JsonNode eNode = root.get("e");
      if (eNode != null) {
        builder.end(eNode.asLong());
      }
      JsonNode dNode = root.get("d");
      if (dNode != null) {
        builder.description(dNode.asText());
      }
      JsonNode iNode = root.get("i");
      if (iNode != null) {
        builder.traceId(parseUnsignedHexLong(iNode.asText()));
      }
      JsonNode sNode = root.get("s");
      if (sNode != null) {
        builder.spanId(parseUnsignedHexLong(sNode.asText()));
      }
      JsonNode rNode = root.get("r");
      if (rNode != null) {
        builder.processId(rNode.asText());
      }
      JsonNode parentsNode = root.get("p");
      LinkedList<Long> parents = new LinkedList<Long>();
      if (parentsNode != null) {
        for (Iterator<JsonNode> iter = parentsNode.elements();
             iter.hasNext(); ) {
          JsonNode parentIdNode = iter.next();
          parents.add(parseUnsignedHexLong(parentIdNode.asText()));
        }
      }
      builder.parents(parents);
      JsonNode traceInfoNode = root.get("n");
      if (traceInfoNode != null) {
        HashMap<String, String> traceInfo = new HashMap<String, String>();
        for (Iterator<String> iter = traceInfoNode.fieldNames();
             iter.hasNext(); ) {
          String field = iter.next();
          traceInfo.put(field, traceInfoNode.get(field).asText());
        }
        builder.traceInfo(traceInfo);
      }
      JsonNode timelineNode = root.get("t");
      if (timelineNode != null) {
        LinkedList<TimelineAnnotation> timeline =
            new LinkedList<TimelineAnnotation>();
        for (Iterator<JsonNode> iter = timelineNode.elements();
             iter.hasNext(); ) {
          JsonNode ann = iter.next();
          timeline.add(new TimelineAnnotation(ann.get("t").asLong(),
              ann.get("m").asText()));
        }
        builder.timeline(timeline);
      }
      return builder.build();
    }
  }
}
