content: /*
   * Created by LuaView.
   * Copyright (c) 2017, Alibaba Group. All rights reserved.
   *
   * This source code is licensed under the MIT.
   * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
   */
  
  package com.taobao.luaview.util;
  
  import android.util.Log;
  
  import com.facebook.csslayout.CSSAlign;
  import com.facebook.csslayout.CSSFlexDirection;
  import com.facebook.csslayout.CSSJustify;
  import com.facebook.csslayout.CSSNode;
  import com.facebook.csslayout.CSSPositionType;
  import com.facebook.csslayout.CSSWrap;
  import com.facebook.csslayout.Spacing;
  import com.taobao.luaview.util.DimenUtil;
  
  import java.util.Arrays;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.List;
  import java.util.Map;
  import java.util.Set;
  
  /**
   * Created by xiekaiwei on 16/3/17.
   */
  public class FlexboxCSSParser {
      private static final String TAG = "FlexboxCSSParser";
      private static final String POSITION = "position";
      private static final String ABSOLUTE = "absolute";
      private static final String TOP = "top";
      private static final String LEFT = "left";
      private static final String BOTTOM = "bottom";
      private static final String RIGHT = "right";
      private static final String FLEXDEIRECTION = "flex-direction";
      private static final String FLEXDIRECTIONROW = "row";
      private static final String FLEXDIRECTIONROWREVERSE = "row-reverse";
      private static final String FLEXDIRECTIONCOLUMN = "column";
      private static final String FLEXDIRECTIONCOLUMNREVERSE = "column-reverse";
      private static final String ALIGNITEMS = "align-items";
      private static final String ALIGNCONTENT = "align-content";
      private static final String ALIGNSELF = "align-self";
      private static final String ALIGNAUTO = "auto";
      private static final String ALIGNSTART = "flex-start";
      private static final String ALIGNCENTER = "center";
      private static final String ALIGNEND = "flex-end";
      private static final String ALIGNSTRETCH = "stretch";
      private static final String JUSTIFYCONTENT = "justify-content";
      private static final String JUSTIFYCONTENTSTART = "flex-start";
      private static final String JUSTIFYCONTENTCENTER = "center";
      private static final String JUSTIFYCONTENTEND = "flex-end";
      private static final String JUSTIFYCONTENTBETWEEN = "space-between";
      private static final String JUSTIFYCONTENTAROUND = "space-around";
      private static final String FLEX = "flex";
      private static final String FLEXWRAP = "flex-wrap";
      private static final String WIDTH = "width";
      private static final String HEIGHT = "height";
      private static final String MINWIDTH = "min-width";
      private static final String MINHEIGHT = "min-height";
      private static final String MAXWIDTH = "max-height";
      private static final String MAXHEIGHT = "max-height";
      private static final String MARGIN = "margin";
      private static final String MARGINLEFT = "margin-left";
      private static final String MARGINTOP = "margin-top";
      private static final String MARGINBOTTOM = "margin-bottom";
      private static final String MARGINRIGHT = "margin-right";
      private static final String PADDING = "padding";
      private static final String PADDINGLEFT = "padding-left";
      private static final String PADDINGTOP = "padding-top";
      private static final String PADDINGBOTTOM = "padding-bottom";
      private static final String PADDINGRIGHT = "padding-right";
      private static final String SIZETOFIT = "sizetofit";
  
      private static Map<String, String> mInlineMap;
      private static String mCssString;
      private static CSSNode mNode;
  
      public static void parseFlexNodeCSS(CSSNode node, String cssString) {
          if (mCssString == cssString || mNode == node) {
              return;
          }
  
          mCssString = cssString;
          mNode = node;
          resetInlineMap();
  
          setPosition();
          setDirection();
          setAlignItems();
          setAlignSelf();
          setAlignContent();
          setJustfiyContent();
          setFlex();
          setFlexWrap();
          setSize();
          setMinSize();
          setMaxSize();
          setMargin();
          setPadding();
          setSizeToFit();
      }
  
      private static float pixelFloat(String num) {
          float fnum = Float.parseFloat(num);
          return DimenUtil.dpiToPx(fnum);
      }
  
      private static void setPosition() {
          String position = mInlineMap.get(POSITION);
          Log.d(TAG, "setPosition: with postion" + position);
          if (position != null && position.equals(ABSOLUTE)) {
              mNode.setPositionType(CSSPositionType.ABSOLUTE);
  
              String top = mInlineMap.get(TOP);
              if (top != null) {
                  mNode.setPositionTop(pixelFloat(top));
              }
  
              String left = mInlineMap.get(LEFT);
              if (left != null) {
                  mNode.setPositionLeft(pixelFloat(left));
              }
  
              String bottom = mInlineMap.get(BOTTOM);
              if (bottom != null) {
                  mNode.setPositionBottom(pixelFloat(bottom));
              }
  
              String right = mInlineMap.get(RIGHT);
              if (right != null) {
                  mNode.setPositionRight(pixelFloat(right));
              }
          }
      }
  
      private static void setDirection() {
          String direction = mInlineMap.get(FLEXDEIRECTION);
          if (direction != null) {
              CSSFlexDirection dir = directionMap.get(direction);
              if (dir != null) {
                  mNode.setFlexDirection(dir);
              }
          }
      }
  
      private static void setAlignItems() {
          String alignItems = mInlineMap.get(ALIGNITEMS);
          if (alignItems != null) {
              CSSAlign align = alignMap.get(alignItems);
              if (align != null) {
                  mNode.setAlignItems(align);
              }
          }
      }
  
      private static void setAlignSelf() {
          String alignSelf = mInlineMap.get(ALIGNSELF);
          if (alignSelf != null) {
              CSSAlign align = alignMap.get(alignSelf);
              if (align != null) {
                  mNode.setAlignSelf(align);
              }
          }
      }
  
      private static void setAlignContent() {
          String alignContent = mInlineMap.get(ALIGNCONTENT);
          if (alignContent != null) {
              CSSAlign align = alignMap.get(alignContent);
              if (align != null) {
                  mNode.setAlignContent(align);
              }
          }
      }
  
      private static void setJustfiyContent() {
          String justifyContent = mInlineMap.get(JUSTIFYCONTENT);
          if (justifyContent != null) {
              CSSJustify juc = justifyMap.get(justifyContent);
              if (juc != null) {
                  mNode.setJustifyContent(juc);
              }
          }
      }
  
      private static void setFlex() {
          String flex = mInlineMap.get(FLEX);
          if (flex != null) {
              mNode.setFlex(Float.parseFloat(flex));
          }
      }
  
      private static void setFlexWrap() {
          String flexWrap = mInlineMap.get(FLEXWRAP);
          if (flexWrap != null) {
              CSSWrap ifWrap = Integer.parseInt(flexWrap) > 0 ? CSSWrap.WRAP : CSSWrap.NOWRAP;
              mNode.setWrap(ifWrap);
          }
      }
  
      private static void setSize() {
          String width = mInlineMap.get(WIDTH);
          if (width != null) {
              mNode.setStyleWidth(pixelFloat(width));
          }
  
          String height = mInlineMap.get(HEIGHT);
          if (height != null) {
              mNode.setStyleHeight(pixelFloat(height));
          }
      }
  
      private static void setMinSize() {
          String width = mInlineMap.get(MINWIDTH);
          if (width != null) {
              mNode.setStyleMinWidth(pixelFloat(width));
          }
  
          String height = mInlineMap.get(MINHEIGHT);
          if (height != null) {
              mNode.setStyleMinWidth(pixelFloat(height));
          }
      }
  
      private static void setMaxSize() {
          String width = mInlineMap.get(MAXWIDTH);
          if (width != null) {
              mNode.setStyleMaxWidth(pixelFloat(width));
          }
  
          String height = mInlineMap.get(MAXHEIGHT);
          if (height != null) {
              mNode.setStyleMaxHeight(pixelFloat(height));
          }
      }
  
      private static void setMargin() {
          String margin = mInlineMap.get(MARGIN);
          if (margin != null) {
              Float fMargin = pixelFloat(margin);
              mNode.setMargin(Spacing.LEFT, fMargin);
              mNode.setMargin(Spacing.TOP, fMargin);
              mNode.setMargin(Spacing.BOTTOM, fMargin);
              mNode.setMargin(Spacing.RIGHT, fMargin);
          }
  
          String marginLeft = mInlineMap.get(MARGINLEFT);
          if (marginLeft != null) {
              mNode.setMargin(Spacing.LEFT, pixelFloat(marginLeft));
          }
  
          String marginTop = mInlineMap.get(MARGINTOP);
          if (marginTop != null) {
              mNode.setMargin(Spacing.TOP, pixelFloat(marginTop));
          }
  
          String marginBottom = mInlineMap.get(MARGINBOTTOM);
          if (marginBottom != null) {
              mNode.setMargin(Spacing.BOTTOM, pixelFloat(marginBottom));
          }
  
          String marginRight = mInlineMap.get(MARGINRIGHT);
          if (marginRight != null) {
              mNode.setMargin(Spacing.RIGHT, pixelFloat(marginRight));
          }
      }
  
      private static void setPadding() {
          String padding = mInlineMap.get(PADDING);
          if (padding != null) {
              Float mPadding = pixelFloat(padding);
              mNode.setPadding(Spacing.LEFT, mPadding);
              mNode.setPadding(Spacing.TOP, mPadding);
              mNode.setPadding(Spacing.BOTTOM, mPadding);
              mNode.setPadding(Spacing.RIGHT, mPadding);
          }
  
          String paddingLeft = mInlineMap.get(PADDINGLEFT);
          if (paddingLeft != null) {
              mNode.setPadding(Spacing.LEFT, pixelFloat(paddingLeft));
          }
  
          String paddingTop = mInlineMap.get(PADDINGTOP);
          if (paddingTop != null) {
              mNode.setPadding(Spacing.TOP, pixelFloat(paddingTop));
          }
  
          String paddingBottom = mInlineMap.get(PADDINGBOTTOM);
          if (paddingBottom != null) {
              mNode.setPadding(Spacing.BOTTOM, pixelFloat(paddingBottom));
          }
  
          String paddingRight = mInlineMap.get(PADDINGRIGHT);
          if (paddingRight != null) {
              mNode.setPadding(Spacing.RIGHT, pixelFloat(paddingRight));
          }
      }
  
      private static void setSizeToFit() {
          String fit = mInlineMap.get(SIZETOFIT);
          if (fit != null) {
              mNode.setSizeToFit(Integer.parseInt(fit) > 0);
          }
      }
  
      private static Map<String, String> resetInlineMap() {
          List<String> items = Arrays.asList(mCssString.split("\\s*,\\s*"));
          Map<String, String> resultMap = new HashMap<String, String>();
  
          for (int i = 0; i < items.size(); i++) {
              String kv = items.get(i);
              try {
                  List<String> keyAndValue = Arrays.asList(kv.split("\\s*:\\s*"));
                  String key = keyAndValue.get(0);
                  if (!validCssKeys.contains(key)) {
                      Log.d(TAG, "getInlineMap: with un correct key: " + key + " check in" + validCssKeys);
                  } else {
                      resultMap.put(keyAndValue.get(0), keyAndValue.get(1));
                  }
              } catch (Exception e) {
                  Log.e(TAG, "getInlineMap: wrong", e);
                  continue;
              }
          }
  
          Log.d(TAG, "getInlineMap: " + items + "resultMap: " + resultMap);
          mInlineMap = resultMap;
  
          return mInlineMap;
      }
  
      private static final Set<String> validCssKeys;
  
      static {
          validCssKeys = new HashSet<String>(Arrays.asList(
                  POSITION,
                  TOP,
                  LEFT,
                  RIGHT,
                  BOTTOM,
                  FLEXDEIRECTION,
                  ALIGNITEMS,
                  ALIGNCONTENT,
                  ALIGNSELF,
                  JUSTIFYCONTENT,
                  FLEX,
                  FLEXWRAP,
                  WIDTH,
                  HEIGHT,
                  MINWIDTH,
                  MINHEIGHT,
                  MAXWIDTH,
                  MAXHEIGHT,
                  MARGIN,
                  MARGINLEFT,
                  MARGINTOP,
                  MARGINBOTTOM,
                  MARGINRIGHT,
                  PADDING,
                  PADDINGLEFT,
                  PADDINGTOP,
                  PADDINGBOTTOM,
                  PADDINGRIGHT,
                  SIZETOFIT
          ));
      }
  
      private static final Map<String, CSSFlexDirection> directionMap;
  
      static {
          directionMap = new HashMap<String, CSSFlexDirection>();
          directionMap.put(FLEXDIRECTIONCOLUMN, CSSFlexDirection.COLUMN);
          directionMap.put(FLEXDIRECTIONROW, CSSFlexDirection.ROW);
          directionMap.put(FLEXDIRECTIONCOLUMNREVERSE, CSSFlexDirection.COLUMN_REVERSE);
          directionMap.put(FLEXDIRECTIONROWREVERSE, CSSFlexDirection.ROW_REVERSE);
      }
  
      private static final Map<String, CSSAlign> alignMap;
  
      static {
          alignMap = new HashMap<String, CSSAlign>();
          alignMap.put(ALIGNAUTO, CSSAlign.AUTO);
          alignMap.put(ALIGNCENTER, CSSAlign.CENTER);
          alignMap.put(ALIGNSTART, CSSAlign.FLEX_START);
          alignMap.put(ALIGNEND, CSSAlign.FLEX_END);
          alignMap.put(ALIGNSTRETCH, CSSAlign.STRETCH);
      }
  
      private static final Map<String, CSSJustify> justifyMap;
  
      static {
          justifyMap = new HashMap<String, CSSJustify>();
          justifyMap.put(JUSTIFYCONTENTAROUND, CSSJustify.SPACE_AROUND);
          justifyMap.put(JUSTIFYCONTENTBETWEEN, CSSJustify.SPACE_BETWEEN);
          justifyMap.put(JUSTIFYCONTENTCENTER, CSSJustify.CENTER);
          justifyMap.put(JUSTIFYCONTENTSTART, CSSJustify.FLEX_START);
          justifyMap.put(JUSTIFYCONTENTEND, CSSJustify.FLEX_END);
      }
  }
  