/*
 * Copyright 2016 The Bazel Authors. All rights reserved.
 *
 * 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.idea.blaze.base.lang.buildfile.highlighting;

import com.google.common.collect.ImmutableMap;
import com.google.idea.blaze.base.lang.buildfile.language.BuildFileType;
import com.google.idea.blaze.base.settings.Blaze;
import com.intellij.application.options.colors.InspectionColorSettingsPage;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.fileTypes.SyntaxHighlighter;
import com.intellij.openapi.fileTypes.SyntaxHighlighterFactory;
import com.intellij.openapi.options.colors.AttributesDescriptor;
import com.intellij.openapi.options.colors.ColorDescriptor;
import com.intellij.openapi.options.colors.ColorSettingsPage;
import com.intellij.psi.codeStyle.DisplayPriority;
import com.intellij.psi.codeStyle.DisplayPrioritySortable;
import com.intellij.util.PlatformUtils;
import java.util.Map;
import javax.swing.Icon;

/** Allows user to customize colors. */
public class BuildColorsPage
    implements ColorSettingsPage, InspectionColorSettingsPage, DisplayPrioritySortable {
  private static final AttributesDescriptor[] ATTRS =
      new AttributesDescriptor[] {
        new AttributesDescriptor("Keyword", BuildSyntaxHighlighter.BUILD_KEYWORD),
        new AttributesDescriptor("String", BuildSyntaxHighlighter.BUILD_STRING),
        new AttributesDescriptor("Number", BuildSyntaxHighlighter.BUILD_NUMBER),
        new AttributesDescriptor("Line Comment", BuildSyntaxHighlighter.BUILD_LINE_COMMENT),
        new AttributesDescriptor("Operation Sign", BuildSyntaxHighlighter.BUILD_OPERATION_SIGN),
        new AttributesDescriptor("Parentheses", BuildSyntaxHighlighter.BUILD_PARENS),
        new AttributesDescriptor("Brackets", BuildSyntaxHighlighter.BUILD_BRACKETS),
        new AttributesDescriptor("Braces", BuildSyntaxHighlighter.BUILD_BRACES),
        new AttributesDescriptor("Comma", BuildSyntaxHighlighter.BUILD_COMMA),
        new AttributesDescriptor("Dot", BuildSyntaxHighlighter.BUILD_DOT),
        new AttributesDescriptor("Function definition", BuildSyntaxHighlighter.BUILD_FN_DEFINITION),
        new AttributesDescriptor("Parameter", BuildSyntaxHighlighter.BUILD_PARAMETER),
        new AttributesDescriptor("Keyword argument", BuildSyntaxHighlighter.BUILD_KEYWORD_ARG),
      };

  private static final Map<String, TextAttributesKey> ourTagToDescriptorMap =
      ImmutableMap.<String, TextAttributesKey>builder()
          .put("funcDef", BuildSyntaxHighlighter.BUILD_FN_DEFINITION)
          .put("param", BuildSyntaxHighlighter.BUILD_PARAMETER)
          .put("kwarg", BuildSyntaxHighlighter.BUILD_KEYWORD_ARG)
          .put("comma", BuildSyntaxHighlighter.BUILD_COMMA)
          .put("number", BuildSyntaxHighlighter.BUILD_NUMBER)
          .build();

  @Override
  public String getDisplayName() {
    return Blaze.defaultBuildSystemName() + " BUILD files";
  }

  @Override
  public Icon getIcon() {
    return BuildFileType.INSTANCE.getIcon();
  }

  @Override
  public AttributesDescriptor[] getAttributeDescriptors() {
    return ATTRS;
  }

  @Override
  public ColorDescriptor[] getColorDescriptors() {
    return ColorDescriptor.EMPTY_ARRAY;
  }

  @Override
  public SyntaxHighlighter getHighlighter() {
    final SyntaxHighlighter highlighter =
        SyntaxHighlighterFactory.getSyntaxHighlighter(BuildFileType.INSTANCE, null, null);
    assert highlighter != null;
    return highlighter;
  }

  @Override
  public String getDemoText() {
    return "def <funcDef>function</funcDef>(<param>x</param>, <kwarg>whatever</kwarg>=1):\n"
        + "    s = (\"Test\", 2+3, {'a': 'b'}, <param>x</param>)   # Comment\n"
        + "    print s[0].lower()\n"
        + "\n"
        + "java_library(\n"
        + "    <kwarg>name</kwarg> = \"lib\",\n"
        + "    <kwarg>srcs</kwarg> = glob([\"**/*.java\"]),\n"
        + ")\n";
  }

  @Override
  public Map<String, TextAttributesKey> getAdditionalHighlightingTagToDescriptorMap() {
    return ourTagToDescriptorMap;
  }

  @Override
  public DisplayPriority getPriority() {
    return PlatformUtils.isPyCharm()
        ? DisplayPriority.KEY_LANGUAGE_SETTINGS
        : DisplayPriority.LANGUAGE_SETTINGS;
  }
}
