// Copyright 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.

package com.google.gwtorm.nosql;

import com.google.gwtorm.protobuf.ProtobufCodec;
import com.google.protobuf.CodedInputStream;
import com.google.protobuf.CodedOutputStream;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.WireFormat;

import java.io.EOFException;
import java.io.IOException;

/** Encodes a relation number in front of an object. */
public class RelationCodec<T> extends ProtobufCodec<T> {
  /**
   * Pop the field number from the stream and return it.
   *
   * @param in the stream to pop the field number from. The caller is
   *        responsible for making sure the underlying stream had a mark set for
   *        at least 8 bytes so the tag can be examined, reset, and later read
   *        again during mergeFrom or decode.
   * @return the field number of the relation.
   * @throws IOException the stream cannot be read.
   */
  public static int peekId(CodedInputStream in) throws IOException {
    return in.readTag() >>> 3;
  }

  private final int fieldId;
  private final ProtobufCodec<T> objectCodec;

  public RelationCodec(int fieldId, ProtobufCodec<T> objectCodec) {
    this.fieldId = fieldId;
    this.objectCodec = objectCodec;
  }

  @Override
  public T newInstance() {
    return objectCodec.newInstance();
  }

  @Override
  public int sizeof(T obj) {
    int sz = objectCodec.sizeof(obj);
    return CodedOutputStream.computeTagSize(fieldId) //
        + CodedOutputStream.computeRawVarint32Size(sz) //
        + sz;
  }

  @Override
  public void encode(T obj, CodedOutputStream out) throws IOException {
    int sz = objectCodec.sizeof(obj);
    out.writeTag(fieldId, WireFormat.FieldType.MESSAGE.getWireType());
    out.writeRawVarint32(sz);
    objectCodec.encode(obj, out);
  }

  @Override
  public void mergeFrom(CodedInputStream in, T obj) throws IOException {
    boolean found = false;
    for (;;) {
      int tag = in.readTag();
      if (tag == 0) {
        if (found) {
          break;
        } else {
          // Reached EOF. But we require an object in our only field.
          throw new EOFException("Expected field " + fieldId);
        }
      }

      if ((tag >>> 3) == fieldId) {
        if ((tag & 0x7) == WireFormat.FieldType.MESSAGE.getWireType()) {
          int sz = in.readRawVarint32();
          int oldLimit = in.pushLimit(sz);
          objectCodec.mergeFrom(in, obj);
          in.checkLastTagWas(0);
          in.popLimit(oldLimit);
          found = true;
        } else {
          throw new InvalidProtocolBufferException("Field " + fieldId
              + " should be length delimited (wire type 2)");
        }
      } else {
        in.skipField(tag);
      }
    }
  }
}
