// Copyright (C) 2019 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 com.googlesource.gerrit.plugins.task;

import com.googlesource.gerrit.plugins.task.TaskConfig.Task;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.jgit.errors.ConfigInvalidException;

/** Use to pre-load a task definition with values from its preload-task definition. */
public class Preloader {
  public static void preload(Task definition) throws ConfigInvalidException {
    String name = definition.preloadTask;
    if (name != null) {
      Task task = definition.config.getTaskOptional(name);
      if (task != null) {
        preload(task);
        preloadFrom(definition, task);
      }
    }
  }

  protected static void preloadFrom(Task definition, Task preloadFrom) {
    for (Field field : definition.getClass().getFields()) {
      String name = field.getName();
      if ("isVisible".equals(name) || "isTrusted".equals(name) || "config".equals(name)) {
        continue;
      }

      try {
        field.setAccessible(true);
        preloadField(field.getType(), field, definition, preloadFrom);
      } catch (IllegalAccessException | IllegalArgumentException e) {
        throw new RuntimeException();
      }
    }
  }

  protected static <T, S, K, V> void preloadField(
      Class<T> clz, Field field, Task definition, Task preloadFrom)
      throws IllegalArgumentException, IllegalAccessException {
    T pre = getField(clz, field, preloadFrom);
    if (pre != null) {
      T val = getField(clz, field, definition);
      if (val == null) {
        field.set(definition, pre);
      } else if (val instanceof List) {
        List<?> valList = List.class.cast(val);
        List<?> preList = List.class.cast(pre);
        field.set(definition, preloadListFrom(castUnchecked(valList), castUnchecked(preList)));
      } else if (val instanceof Map) {
        Map<?, ?> valMap = Map.class.cast(val);
        Map<?, ?> preMap = Map.class.cast(pre);
        field.set(definition, preloadMapFrom(castUnchecked(valMap), castUnchecked(preMap)));
      } // nothing to do for overridden preloaded scalars
    }
  }

  protected static <T> T getField(Class<T> clz, Field field, Object obj)
      throws IllegalArgumentException, IllegalAccessException {
    return clz.cast(field.get(obj));
  }

  @SuppressWarnings("unchecked")
  protected static <S> List<S> castUnchecked(List<?> list) {
    List<S> forceCheck = (List<S>) list;
    return forceCheck;
  }

  @SuppressWarnings("unchecked")
  protected static <K, V> Map<K, V> castUnchecked(Map<?, ?> map) {
    Map<K, V> forceCheck = (Map<K, V>) map;
    return forceCheck;
  }

  protected static <T> List<T> preloadListFrom(List<T> list, List<T> preList) {
    List<T> extended = list;
    if (!preList.isEmpty()) {
      extended = preList;
      if (!list.isEmpty()) {
        extended = new ArrayList<>(list.size() + preList.size());
        extended.addAll(preList);
        extended.addAll(list);
      }
    }
    return extended;
  }

  protected static <K, V> Map<K, V> preloadMapFrom(Map<K, V> map, Map<K, V> preMap) {
    Map<K, V> extended = map;
    if (!preMap.isEmpty()) {
      extended = preMap;
      if (!map.isEmpty()) {
        extended = new HashMap<>(map.size() + preMap.size());
        extended.putAll(preMap);
        extended.putAll(map);
      }
    }
    return extended;
  }
}
