// Copyright (C) 2013 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.google.gerrit.client.projects;

import com.google.gerrit.client.ErrorDialog;
import com.google.gerrit.client.actions.ActionInfo;
import com.google.gerrit.client.rpc.NativeMap;
import com.google.gerrit.extensions.api.projects.ProjectState;
import com.google.gerrit.extensions.common.InheritableBoolean;
import com.google.gerrit.extensions.common.SubmitType;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.core.client.JsArrayString;
import com.google.gwtexpui.safehtml.client.FindReplace;
import com.google.gwtexpui.safehtml.client.LinkFindReplace;
import com.google.gwtexpui.safehtml.client.RawFindReplace;

import java.util.ArrayList;
import java.util.List;

public class ConfigInfo extends JavaScriptObject {

  public final native String description()
  /*-{ return this.description }-*/;

  public final native InheritedBooleanInfo require_change_id()
  /*-{ return this.require_change_id; }-*/;

  public final native InheritedBooleanInfo use_content_merge()
  /*-{ return this.use_content_merge; }-*/;

  public final native InheritedBooleanInfo use_contributor_agreements()
  /*-{ return this.use_contributor_agreements; }-*/;

  public final native InheritedBooleanInfo use_signed_off_by()
  /*-{ return this.use_signed_off_by; }-*/;

  public final SubmitType submit_type() {
    return SubmitType.valueOf(submit_typeRaw());
  }

  public final native NativeMap<NativeMap<ConfigParameterInfo>> pluginConfig()
  /*-{ return this.plugin_config || {}; }-*/;

  public final native NativeMap<ConfigParameterInfo> pluginConfig(String p)
  /*-{ return this.plugin_config[p]; }-*/;

  public final native NativeMap<ActionInfo> actions()
  /*-{ return this.actions; }-*/;

  private final native String submit_typeRaw()
  /*-{ return this.submit_type }-*/;

  public final ProjectState state() {
    if (stateRaw() == null) {
      return ProjectState.ACTIVE;
    }
    return ProjectState.valueOf(stateRaw());
  }
  private final native String stateRaw()
  /*-{ return this.state }-*/;

  public final native MaxObjectSizeLimitInfo max_object_size_limit()
  /*-{ return this.max_object_size_limit; }-*/;

  private final native NativeMap<CommentLinkInfo> commentlinks0()
  /*-{ return this.commentlinks; }-*/;
  final List<FindReplace> commentlinks() {
    JsArray<CommentLinkInfo> cls = commentlinks0().values();
    List<FindReplace> commentLinks = new ArrayList<>(cls.length());
    for (int i = 0; i < cls.length(); i++) {
      CommentLinkInfo cl = cls.get(i);
      if (!cl.enabled()) {
        continue;
      }
      if (cl.link() != null) {
        commentLinks.add(new LinkFindReplace(cl.match(), cl.link()));
      } else {
        try {
          FindReplace fr = new RawFindReplace(cl.match(), cl.html());
          commentLinks.add(fr);
        } catch (RuntimeException e) {
          int index = e.getMessage().indexOf("at Object");
          new ErrorDialog("Invalid commentlink configuration: "
              + (index == -1
              ? e.getMessage()
              : e.getMessage().substring(0, index))).center();
        }
      }
    }
    return commentLinks;
  }

  final native ThemeInfo theme() /*-{ return this.theme; }-*/;

  protected ConfigInfo() {
  }

  static class CommentLinkInfo extends JavaScriptObject {
    final native String match() /*-{ return this.match; }-*/;
    final native String link() /*-{ return this.link; }-*/;
    final native String html() /*-{ return this.html; }-*/;
    final native boolean enabled() /*-{
      return !this.hasOwnProperty('enabled') || this.enabled;
    }-*/;

    protected CommentLinkInfo() {
    }
  }

  public static class InheritedBooleanInfo extends JavaScriptObject {
    public static InheritedBooleanInfo create() {
      return (InheritedBooleanInfo) createObject();
    }

    public final native boolean value()
    /*-{ return this.value ? true : false; }-*/;

    public final native boolean inherited_value()
    /*-{ return this.inherited_value ? true : false; }-*/;

    public final InheritableBoolean configured_value() {
      return InheritableBoolean.valueOf(configured_valueRaw());
    }
    private final native String configured_valueRaw()
    /*-{ return this.configured_value }-*/;

    public final void setConfiguredValue(InheritableBoolean v) {
      setConfiguredValueRaw(v.name());
    }
    public final native void setConfiguredValueRaw(String v)
    /*-{ if(v)this.configured_value=v; }-*/;

    protected InheritedBooleanInfo() {
    }
  }

  public static class MaxObjectSizeLimitInfo extends JavaScriptObject {
    public final native String value() /*-{ return this.value; }-*/;
    public final native String inherited_value() /*-{ return this.inherited_value; }-*/;
    public final native String configured_value() /*-{ return this.configured_value }-*/;

    protected MaxObjectSizeLimitInfo() {
    }
  }

  public static class ConfigParameterInfo extends JavaScriptObject {
    public final native String name() /*-{ return this.name; }-*/;
    public final native String displayName() /*-{ return this.display_name; }-*/;
    public final native String description() /*-{ return this.description; }-*/;
    public final native String warning() /*-{ return this.warning; }-*/;
    public final native String type() /*-{ return this.type; }-*/;
    public final native String value() /*-{ return this.value; }-*/;
    public final native boolean editable() /*-{ return this.editable ? true : false; }-*/;
    public final native boolean inheritable() /*-{ return this.inheritable ? true : false; }-*/;
    public final native String configuredValue() /*-{ return this.configured_value; }-*/;
    public final native String inheritedValue() /*-{ return this.inherited_value; }-*/;
    public final native JsArrayString permittedValues()  /*-{ return this.permitted_values; }-*/;
    public final native JsArrayString values()  /*-{ return this.values; }-*/;

    protected ConfigParameterInfo() {
    }
  }

  public static class ConfigParameterValue extends JavaScriptObject {
    final native void init() /*-{ this.values = []; }-*/;
    final native void add_value(String v) /*-{ this.values.push(v); }-*/;
    final native void set_value(String v) /*-{ if(v)this.value = v; }-*/;
    public static ConfigParameterValue create() {
      ConfigParameterValue v = createObject().cast();
      return v;
    }

    public final ConfigParameterValue values(String[] values) {
      init();
      for (String v : values) {
        add_value(v);
      }
      return this;
    }

    public final ConfigParameterValue value(String v) {
      set_value(v);
      return this;
    }

    protected ConfigParameterValue() {
    }
  }
}
