// Copyright (C) 2015 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.rabbitmq.config.section;

import com.googlesource.gerrit.plugins.rabbitmq.annotation.Default;
import com.googlesource.gerrit.plugins.rabbitmq.annotation.Limit;
import java.lang.reflect.Field;
import java.util.Set;
import org.eclipse.jgit.lib.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public final class Sections {
  private static final Logger LOGGER = LoggerFactory.getLogger(Sections.class);

  public static <T extends Section> String getName(T section) {
    return section.getClass().getSimpleName().toLowerCase();
  }

  public static <T extends Section> T initialize(T section) {
    Field[] fs = section.getClass().getFields();
    for (Field f : fs) {
      try {
        if (f.isAnnotationPresent(Default.class)) {
          Default a = f.getAnnotation(Default.class);
          Class<?> type = f.getType();
          if (type == String.class) {
            f.set(section, a.value());
          } else if (type == Integer.class) {
            f.set(section, Integer.valueOf(a.value()));
          } else if (type == Long.class) {
            f.set(section, Long.valueOf(a.value()));
          } else if (type == Boolean.class) {
            f.set(section, Boolean.valueOf(a.value()));
          }
        }
      } catch (IllegalAccessException ex) {
        LOGGER.warn("Cannot access field {}. Cause: {}", f.getName(), ex.getMessage());
      }
    }
    return section;
  }

  public static <T extends Section> Config toConfig(T section) {
    return toConfig(section, new Config());
  }

  public static <T extends Section> Config toConfig(T section, Config config) {
    Field[] fs = section.getClass().getFields();
    for (Field f : fs) {
      try {
        Class<?> type = f.getType();
        Object obj = f.get(section);
        if (obj != null) {
          if (type == String.class) {
            config.setString(getName(section), null, f.getName(), String.class.cast(obj));
          } else if (type == Integer.class) {
            config.setInt(getName(section), null, f.getName(), Integer.class.cast(obj));
          } else if (type == Long.class) {
            config.setLong(getName(section), null, f.getName(), Long.class.cast(obj));
          } else if (type == Boolean.class) {
            config.setBoolean(getName(section), null, f.getName(), Boolean.class.cast(obj));
          }
        }
      } catch (IllegalAccessException ex) {
        LOGGER.warn("Cannot access field {}. Cause: {}", f.getName(), ex.getMessage());
      }
    }
    return config;
  }

  public static <T extends Section> Section fromConfig(T section, Config... configs) {
    for (Config config : configs) {
      if (config != null) {
        Set<String> names = config.getNames(getName(section));
        Field[] fs = section.getClass().getFields();

        for (Field f : fs) {
          try {
            if (names.contains(f.getName())) {
              Class<?> type = f.getType();
              if (type == String.class) {
                f.set(section, config.getString(getName(section), null, f.getName()));
              } else if (type == Integer.class) {
                f.set(section, config.getInt(getName(section), null, f.getName(), 0));
              } else if (type == Long.class) {
                f.set(section, config.getLong(getName(section), null, f.getName(), 0));
              } else if (type == Boolean.class) {
                f.set(section, config.getBoolean(getName(section), null, f.getName(), false));
              }
            }
          } catch (IllegalAccessException ex) {
            LOGGER.warn("Cannot access field {}. Cause: {}", f.getName(), ex.getMessage());
          }
        }
      }
    }
    return section;
  }

  public static <T extends Section> T normalize(T section) {
    Field[] fs = section.getClass().getFields();
    for (Field f : fs) {
      try {
        if (f.getType() == Integer.class && f.isAnnotationPresent(Limit.class)) {
          Object obj = f.get(section);
          if (obj != null) {
            Integer val = Integer.class.cast(obj);
            Limit a = f.getAnnotation(Limit.class);
            if (a.min() != -1 && val < a.min()) {
              val = a.min();
            }
            if (a.max() != -1 && val > a.max()) {
              val = a.max();
            }
            f.set(section, val);
          }
        }
      } catch (IllegalAccessException ex) {
        LOGGER.warn("Cannot access field {}. Cause: {}", f.getName(), ex.getMessage());
      }
    }
    return section;
  }
}
