// Copyright (C) 2009 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.

package org.eclipse.jgit.diff;

import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

public class EditDeserializer implements JsonDeserializer<Edit>, JsonSerializer<Edit> {
  @Override
  public Edit deserialize(
      final JsonElement json, final Type typeOfT, final JsonDeserializationContext context)
      throws JsonParseException {
    if (json.isJsonNull()) {
      return null;
    }
    if (!json.isJsonArray()) {
      throw new JsonParseException("Expected array for Edit type");
    }

    final JsonArray o = (JsonArray) json;
    final int cnt = o.size();
    if (cnt < 4 || cnt % 4 != 0) {
      throw new JsonParseException("Expected array of 4 for Edit type");
    }

    if (4 == cnt) {
      return new Edit(get(o, 0), get(o, 1), get(o, 2), get(o, 3));
    }

    List<Edit> l = new ArrayList<>((cnt / 4) - 1);
    for (int i = 4; i < cnt; ) {
      int as = get(o, i++);
      int ae = get(o, i++);
      int bs = get(o, i++);
      int be = get(o, i++);
      l.add(new Edit(as, ae, bs, be));
    }
    return new ReplaceEdit(get(o, 0), get(o, 1), get(o, 2), get(o, 3), l);
  }

  private static int get(final JsonArray a, final int idx) throws JsonParseException {
    final JsonElement v = a.get(idx);
    if (!v.isJsonPrimitive()) {
      throw new JsonParseException("Expected array of 4 for Edit type");
    }
    final JsonPrimitive p = (JsonPrimitive) v;
    if (!p.isNumber()) {
      throw new JsonParseException("Expected array of 4 for Edit type");
    }
    return p.getAsInt();
  }

  @Override
  public JsonElement serialize(
      final Edit src, final Type typeOfSrc, final JsonSerializationContext context) {
    if (src == null) {
      return JsonNull.INSTANCE;
    }
    final JsonArray a = new JsonArray();
    add(a, src);
    if (src instanceof ReplaceEdit) {
      for (Edit e : ((ReplaceEdit) src).getInternalEdits()) {
        add(a, e);
      }
    }
    return a;
  }

  private void add(final JsonArray a, final Edit src) {
    a.add(new JsonPrimitive(src.getBeginA()));
    a.add(new JsonPrimitive(src.getEndA()));
    a.add(new JsonPrimitive(src.getBeginB()));
    a.add(new JsonPrimitive(src.getEndB()));
  }
}
