/*
 * Copyright 2000-2016 JetBrains s.r.o.
 *
 * 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.intellij.openapi.editor.colors.impl;

import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.ColorUtil;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;

import java.awt.Color;

/**
 * This class is intended to read a value from the value element
 * that is the element, which value is defined in the {@code value} attribute.
 * Also it may have the following platform-specific attributes:
 * {@code windows}, {@code mac}, {@code linux}.  If one of them is set,
 * it should be used instead of the default one.
 *
 * @author Sergey.Malenkov
 */
@SuppressWarnings("UseJBColor")
class ValueElementReader {
  @NonNls private static final String VALUE = "value";
  @NonNls private static final String MAC = "mac";
  @NonNls private static final String LINUX = "linux";
  @NonNls private static final String WINDOWS = "windows";
  private static final String OS = SystemInfo.isWindows ? WINDOWS : SystemInfo.isMac ? MAC : LINUX;
  private static final Logger LOG = Logger.getInstance(ValueElementReader.class);

  private String myAttribute;

  /**
   * Initializes the attribute that should be checked before
   * the {@code value} attribute and before the platform-specific attributes.
   *
   * @param attribute the priority attribute
   */
  public void setAttribute(String attribute) {
    myAttribute = StringUtil.isEmpty(attribute) ? null : attribute;
  }

  /**
   * Reads a value of the specified type from the given element.
   *
   * @param type    the class that defines the result type
   * @param element the value element
   * @param <T>     the result type
   * @return a value or {@code null} if it cannot be read
   */
  @Nullable
  public <T> T read(Class<T> type, Element element) {
    T value = null;
    if (element != null) {
      if (myAttribute != null) {
        value = read(type, element, myAttribute);
      }
      if (value == null) {
        value = read(type, element, OS);
        if (value == null) {
          value = read(type, element, VALUE);
        }
      }
    }
    return value;
  }

  /**
   * Reads a value of the specified type
   * from the specified attribute of the given element.
   *
   * @param type      the class that defines the result type
   * @param element   the value element
   * @param attribute the attribute that contains a value
   * @param <T>       the result type
   * @return a value or {@code null} if it cannot be read
   */
  private <T> T read(Class<T> type, Element element, String attribute) {
    String value = element.getAttributeValue(attribute);
    if (value != null) {
      value = value.trim();
      if (value.isEmpty()) {
        if (LOG.isDebugEnabled()) LOG.debug("empty attribute: " + attribute);
      }
      else {
        try {
          return convert(type, value);
        }
        catch (Exception exception) {
          if (LOG.isDebugEnabled()) LOG.debug("wrong attribute: " + attribute, exception);
        }
      }
    }
    return null;
  }

  /**
   * Converts a string value of the specified type
   * from the specified attribute of the given element.
   *
   * @param type  the class that defines the result type
   * @param value a string value to convert
   * @param <T>   the result type
   */
  protected <T> T convert(Class<T> type, String value) {
    if (String.class.equals(type)) {
      //noinspection unchecked
      return (T)value;
    }
    if (Integer.class.equals(type)) {
      //noinspection unchecked
      return (T)Integer.valueOf(value);
    }
    if (Float.class.equals(type)) {
      //noinspection unchecked
      return (T)Float.valueOf(value);
    }
    if (Color.class.equals(type)) {
      //noinspection unchecked
      return (T)toColor(value);
    }
    if (Enum.class.isAssignableFrom(type)) {
      //noinspection unchecked
      return (T)toEnum((Class<Enum>)type, value);
    }
    if (Boolean.class.equals(type)) {
      //noinspection unchecked
      return (T)Boolean.valueOf(value);
    }
    throw new IllegalArgumentException("unsupported " + type);
  }

  private static <T extends Enum> T toEnum(Class<T> type, String value) {
    for (T field : type.getEnumConstants()) {
      if (value.equalsIgnoreCase(field.name()) || value.equals(String.valueOf(field.ordinal()))) {
        return field;
      }
    }
    throw new IllegalArgumentException(value);
  }

  private static Color toColor(String value) {
    try {
      return ColorUtil.fromHex(value);
    }
    catch (Exception exception) {
      LOG.debug(exception);
      int rgb;
      try {
        rgb = Integer.parseInt(value, 16);
      }
      catch (NumberFormatException ignored) {
        rgb = Integer.decode(value);
      }
      return new Color(rgb);
    }
  }
}

@@ -1325,40 +1325,8 @@
  */%0A
-@SuppressWarnings(%22UseJBColor%22)%0A
 clas
@@ -5112,24 +5112,49 @@
  try %7B%0A     
+ if (6 %3C= value.length())
  return Colo
@@ -5167,32 +5167,79 @@
 fromHex(value);%0A
+      LOG.debug(%22short color value: %22, value);%0A
     %7D%0A    catch 
@@ -5278,34 +5278,57 @@
 G.debug(
-exception
+%22wrong color value: %22, value
 );%0A   
+ %7D%0A
    
+ 
 int rgb;
@@ -5328,34 +5328,30 @@
 nt rgb;%0A    
-  
 try %7B%0A
-  
       rgb = 
@@ -5379,30 +5379,26 @@
 e, 16);%0A    
-  %7D%0A  
+%7D%0A
     catch (N
@@ -5431,26 +5431,24 @@
 ed) %7B%0A      
-  
 rgb = Intege
@@ -5464,30 +5464,56 @@
 value);%0A    
-  
 %7D%0A  
+  //noinspection UseJBColor%0A
     return n
@@ -5527,20 +5527,14 @@
 r(rgb);%0A
-    %7D%0A
   %7D%0A%7D%0A

fix short color values in high contrast color scheme