content: /*
   * Copyright (C) 2022 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 androidx.constraintlayout.core.state.helpers;
  
  import static androidx.constraintlayout.core.widgets.ConstraintWidget.HORIZONTAL;
  import static androidx.constraintlayout.core.widgets.ConstraintWidget.UNKNOWN;
  import static androidx.constraintlayout.core.widgets.ConstraintWidget.VERTICAL;
  import static androidx.constraintlayout.core.widgets.Flow.HORIZONTAL_ALIGN_CENTER;
  import static androidx.constraintlayout.core.widgets.Flow.VERTICAL_ALIGN_CENTER;
  import static androidx.constraintlayout.core.widgets.Flow.WRAP_NONE;
  
  import androidx.constraintlayout.core.state.HelperReference;
  import androidx.constraintlayout.core.state.State;
  import androidx.constraintlayout.core.widgets.Flow;
  import androidx.constraintlayout.core.widgets.HelperWidget;
  
  import java.util.HashMap;
  
  /**
   * The FlowReference class can be used to store the relevant properties of a Flow Helper
   * when parsing the Flow Helper information in a JSON representation.
   *
   */
  public class FlowReference extends HelperReference {
      protected Flow mFlow;
  
      protected HashMap<String, Float> mMapWeights;
      protected HashMap<String, Float> mMapPreMargin;
      protected HashMap<String, Float> mMapPostMargin;
  
      protected int mWrapMode = WRAP_NONE;
  
      protected int mVerticalStyle = UNKNOWN;
      protected int mFirstVerticalStyle = UNKNOWN;
      protected int mLastVerticalStyle = UNKNOWN;
      protected int mHorizontalStyle = UNKNOWN;
      protected int mFirstHorizontalStyle = UNKNOWN;
      protected int mLastHorizontalStyle = UNKNOWN;
  
      protected int mVerticalAlign = HORIZONTAL_ALIGN_CENTER;
      protected int mHorizontalAlign = VERTICAL_ALIGN_CENTER;
  
      protected int mVerticalGap = 0;
      protected int mHorizontalGap = 0;
  
      protected int mPaddingLeft = 0;
      protected int mPaddingRight = 0;
      protected int mPaddingTop = 0;
      protected int mPaddingBottom = 0;
  
      protected int mMaxElementsWrap = UNKNOWN;
  
      protected int mOrientation = HORIZONTAL;
  
      protected float mFirstVerticalBias = 0.5f;
      protected float mLastVerticalBias = 0.5f;
      protected float mFirstHorizontalBias = 0.5f;
      protected float mLastHorizontalBias = 0.5f;
  
      public FlowReference(State state, State.Helper type) {
          super(state, type);
          if (type == State.Helper.VERTICAL_FLOW) {
              mOrientation = VERTICAL;
          }
      }
  
      /**
       * Relate widgets to the FlowReference
       *
       * @param id id of a widget
       * @param weight weight of a widget
       * @param preMargin preMargin of a widget
       * @param postMargin postMargin of a widget
       */
      public void addFlowElement(String id, float weight, float preMargin, float postMargin) {
          super.add(id);
          if (!Float.isNaN(weight)) {
              if (mMapWeights == null) {
                  mMapWeights = new HashMap<>();
              }
              mMapWeights.put(id, weight);
          }
          if (!Float.isNaN(preMargin)) {
              if (mMapPreMargin == null) {
                  mMapPreMargin = new HashMap<>();
              }
              mMapPreMargin.put(id, preMargin);
          }
          if (!Float.isNaN(postMargin)) {
              if (mMapPostMargin == null) {
                  mMapPostMargin = new HashMap<>();
              }
              mMapPostMargin.put(id, postMargin);
          }
      }
  
      /**
       * Get the weight of a widget
       *
       * @param id id of a widget
       * @return the weight of a widget
       */
      protected float getWeight(String id) {
          if (mMapWeights == null) {
              return UNKNOWN;
          }
          if (mMapWeights.containsKey(id)) {
              return mMapWeights.get(id);
          }
          return UNKNOWN;
      }
  
      /**
       * Get the post margin of a widget
       *
       * @param id id id of a widget
       * @return the post margin of a widget
       */
      protected float getPostMargin(String id) {
          if (mMapPreMargin != null  && mMapPreMargin.containsKey(id)) {
              return mMapPreMargin.get(id);
          }
          return 0;
      }
  
      /**
       * Get the pre margin of a widget
       *
       * @param id id id of a widget
       * @return the pre margin of a widget
       */
      protected float getPreMargin(String id) {
          if (mMapPostMargin != null  && mMapPostMargin.containsKey(id)) {
              return mMapPostMargin.get(id);
          }
          return 0;
      }
  
      /**
       * Get wrap mode
       *
       * @return wrap mode
       */
      public int getWrapMode() {
          return mWrapMode;
      }
  
      /**
       * Set wrap Mode
       *
       * @param wrap wrap Mode
       */
      public void setWrapMode(int wrap) {
          this.mWrapMode = wrap;
      }
  
      /**
       * Get paddingLeft
       *
       * @return paddingLeft value
       */
      public int getPaddingLeft() {
          return mPaddingLeft;
      }
  
      /**
       * Set paddingLeft
       *
       * @param padding paddingLeft value
       */
      public void setPaddingLeft(int padding) {
          this.mPaddingLeft = padding;
      }
  
      /**
       * Get paddingTop
       *
       * @return paddingTop value
       */
      public int getPaddingTop() {
          return mPaddingTop;
      }
  
      /**
       * Set paddingTop
       *
       * @param padding paddingTop value
       */
      public void setPaddingTop(int padding) {
          this.mPaddingTop = padding;
      }
  
      /**
       * Get paddingRight
       *
       * @return paddingRight value
       */
      public int getPaddingRight() {
          return mPaddingRight;
      }
  
      /**
       * Set paddingRight
       *
       * @param padding paddingRight value
       */
      public void setPaddingRight(int padding) {
          this.mPaddingRight = padding;
      }
  
      /**
       * Get paddingBottom
       *
       * @return paddingBottom value
       */
      public int getPaddingBottom() {
          return mPaddingBottom;
      }
  
      /**
       * Set padding
       *
       * @param padding paddingBottom value
       */
      public void setPaddingBottom(int padding) {
          this.mPaddingBottom = padding;
      }
  
      /**
       * Get vertical style
       *
       * @return vertical style
       */
      public int getVerticalStyle() {
          return mVerticalStyle;
      }
  
      /**
       * set vertical style
       *
       * @param verticalStyle Flow vertical style
       */
      public void setVerticalStyle(int verticalStyle) {
          this.mVerticalStyle = verticalStyle;
      }
  
      /**
       * Get first vertical style
       *
       * @return first vertical style
       */
      public int getFirstVerticalStyle() {
          return mFirstVerticalStyle;
      }
  
      /**
       * Set first vertical style
       *
       * @param firstVerticalStyle Flow first vertical style
       */
      public void setFirstVerticalStyle(int firstVerticalStyle) {
          this.mFirstVerticalStyle = firstVerticalStyle;
      }
  
      /**
       * Get last vertical style
       *
       * @return last vertical style
       */
      public int getLastVerticalStyle() {
          return mLastVerticalStyle;
      }
  
      /**
       * Set last vertical style
       *
       * @param lastVerticalStyle Flow last vertical style
       */
      public void setLastVerticalStyle(int lastVerticalStyle) {
          this.mLastVerticalStyle = lastVerticalStyle;
      }
  
      /**
       * Get horizontal style
       *
       * @return horizontal style
       */
      public int getHorizontalStyle() {
          return mHorizontalStyle;
      }
  
      /**
       * Set horizontal style
       *
       * @param horizontalStyle Flow horizontal style
       */
      public void setHorizontalStyle(int horizontalStyle) {
          this.mHorizontalStyle = horizontalStyle;
      }
  
      /**
       * Get first horizontal style
       *
       * @return first horizontal style
       */
      public int getFirstHorizontalStyle() {
          return mFirstHorizontalStyle;
      }
  
      /**
       * Set first horizontal style
       *
       * @param firstHorizontalStyle Flow first horizontal style
       */
      public void setFirstHorizontalStyle(int firstHorizontalStyle) {
          this.mFirstHorizontalStyle = firstHorizontalStyle;
      }
  
      /**
       * Get last horizontal style
       *
       * @return last horizontal style
       */
      public int getLastHorizontalStyle() {
          return mLastHorizontalStyle;
      }
  
      /**
       * Set last horizontal style
       *
       * @param lastHorizontalStyle Flow last horizontal style
       */
      public void setLastHorizontalStyle(int lastHorizontalStyle) {
          this.mLastHorizontalStyle = lastHorizontalStyle;
      }
  
      /**
       * Get vertical align
       * @return vertical align value
       */
      public int getVerticalAlign() {
          return mVerticalAlign;
      }
  
      /**
       * Set vertical align
       *
       * @param verticalAlign vertical align value
       */
      public void setVerticalAlign(int verticalAlign) {
          this.mVerticalAlign = verticalAlign;
      }
  
      /**
       * Get horizontal align
       *
       * @return horizontal align value
       */
      public int getHorizontalAlign() {
          return mHorizontalAlign;
      }
  
      /**
       * Set horizontal align
       *
       * @param horizontalAlign horizontal align value
       */
      public void setHorizontalAlign(int horizontalAlign) {
          this.mHorizontalAlign = horizontalAlign;
      }
  
      /**
       * Get vertical gap
       *
       * @return vertical gap value
       */
      public int getVerticalGap() {
          return mVerticalGap;
      }
  
      /**
       * Set vertical gap
       *
       * @param verticalGap vertical gap value
       */
      public void setVerticalGap(int verticalGap) {
          this.mVerticalGap = verticalGap;
      }
  
      /**
       * Get horizontal gap
       *
       * @return horizontal gap value
       */
      public int getHorizontalGap() {
          return mHorizontalGap;
      }
  
      /**
       * Set horizontal gap
       *
       * @param horizontalGap horizontal gap value
       */
      public void setHorizontalGap(int horizontalGap) {
          mHorizontalGap = horizontalGap;
      }
  
      /**
       * Get max element wrap
       *
       * @return max element wrap value
       */
      public int getMaxElementsWrap() {
          return mMaxElementsWrap;
      }
  
      /**
       * Set max element wrap
       *
       * @param maxElementsWrap max element wrap value
       */
      public void setMaxElementsWrap(int maxElementsWrap) {
          this.mMaxElementsWrap = maxElementsWrap;
      }
  
      /**
       * Get the orientation of a Flow
       *
       * @return orientation value
       */
      public int getOrientation() {
          return mOrientation;
      }
  
      /**
       * Set the orientation of a Flow
       *
       * @param mOrientation orientation value
       */
      public void setOrientation(int mOrientation) {
          this.mOrientation = mOrientation;
      }
  
      /**
       * Get vertical bias
       *
       * @return vertical bias value
       */
      public float getVerticalBias() {
          return mVerticalBias;
      }
  
  
      /**
       * Get first vertical bias
       *
       * @return first vertical bias value
       */
      public float getFirstVerticalBias() {
          return mFirstVerticalBias;
      }
  
      /**
       * Set first vertical bias
       *
       * @param firstVerticalBias first vertical bias value
       */
      public void setFirstVerticalBias(float firstVerticalBias) {
          this.mFirstVerticalBias = firstVerticalBias;
      }
  
      /**
       * Get last vertical bias
       *
       * @return last vertical bias
       */
      public float getLastVerticalBias() {
          return mLastVerticalBias;
      }
  
      /**
       * Set last vertical bias
       *
       * @param lastVerticalBias last vertical bias value
       */
      public void setLastVerticalBias(float lastVerticalBias) {
          this.mLastVerticalBias = lastVerticalBias;
      }
  
      /**
       * Get horizontal bias
       * @return horizontal bias value
       */
      public float getHorizontalBias() {
          return mHorizontalBias;
      }
  
      /**
       * Get first horizontal bias
       *
       * @return first horizontal bias
       */
      public float getFirstHorizontalBias() {
          return mFirstHorizontalBias;
      }
  
      /**
       * Set first horizontal bias
       *
       * @param firstHorizontalBias first horizontal bias value
       */
      public void setFirstHorizontalBias(float firstHorizontalBias) {
          this.mFirstHorizontalBias = firstHorizontalBias;
      }
  
      /**
       * Get last horizontal bias
       *
       * @return last horizontal bias value
       */
      public float getLastHorizontalBias() {
          return mLastHorizontalBias;
      }
  
      /**
       * Set last horizontal bias
       *
       * @param lastHorizontalBias last horizontal bias value
       */
      public void setLastHorizontalBias(float lastHorizontalBias) {
          this.mLastHorizontalBias = lastHorizontalBias;
      }
  
      @Override
      public HelperWidget getHelperWidget() {
          if (mFlow == null) {
              mFlow = new Flow();
          }
          return mFlow;
      }
  
      @Override
      public void setHelperWidget(HelperWidget widget) {
          if (widget instanceof Flow) {
              mFlow = (Flow) widget;
          } else {
              mFlow = null;
          }
      }
  
      @Override
      public void apply() {
          getHelperWidget();
          this.setConstraintWidget(mFlow);
          mFlow.setOrientation(mOrientation);
          mFlow.setWrapMode(mWrapMode);
  
          if (mMaxElementsWrap != UNKNOWN) {
              mFlow.setMaxElementsWrap(mMaxElementsWrap);
          }
  
          // Padding
          if (mPaddingLeft != 0) {
              mFlow.setPaddingLeft(mPaddingLeft);
          }
          if (mPaddingTop != 0) {
              mFlow.setPaddingTop(mPaddingTop);
          }
          if (mPaddingRight != 0) {
              mFlow.setPaddingRight(mPaddingRight);
          }
          if (mPaddingBottom != 0) {
              mFlow.setPaddingBottom(mPaddingBottom);
          }
  
          // Gap
          if (mHorizontalGap != 0) {
              mFlow.setHorizontalGap(mHorizontalGap);
          }
          if (mVerticalGap != 0) {
              mFlow.setVerticalGap(mVerticalGap);
          }
  
          // Bias
          if (mHorizontalBias != 0.5f) {
              mFlow.setHorizontalBias(mHorizontalBias);
          }
          if (mFirstHorizontalBias != 0.5f) {
              mFlow.setFirstHorizontalBias(mFirstHorizontalBias);
          }
          if (mLastHorizontalBias != 0.5f) {
              mFlow.setLastHorizontalBias(mLastHorizontalBias);
          }
          if (mVerticalBias != 0.5f) {
              mFlow.setVerticalBias(mVerticalBias);
          }
          if (mFirstVerticalBias != 0.5f) {
              mFlow.setFirstVerticalBias(mFirstVerticalBias);
          }
          if (mLastVerticalBias != 0.5f) {
              mFlow.setLastVerticalBias(mLastVerticalBias);
          }
  
          // Align
          if (mHorizontalAlign != HORIZONTAL_ALIGN_CENTER) {
              mFlow.setHorizontalAlign(mHorizontalAlign);
          }
          if (mVerticalAlign != VERTICAL_ALIGN_CENTER) {
              mFlow.setVerticalAlign(mVerticalAlign);
          }
  
          // Style
          if (mVerticalStyle != UNKNOWN) {
              mFlow.setVerticalStyle(mVerticalStyle);
          }
          if (mFirstVerticalStyle != UNKNOWN) {
              mFlow.setFirstVerticalStyle(mFirstVerticalStyle);
          }
          if (mLastVerticalStyle != UNKNOWN) {
              mFlow.setLastVerticalStyle(mLastVerticalStyle);
          }
          if (mHorizontalStyle != UNKNOWN) {
              mFlow.setHorizontalStyle(mHorizontalStyle);
          }
          if (mFirstHorizontalStyle != UNKNOWN) {
              mFlow.setFirstHorizontalStyle(mFirstHorizontalStyle);
          }
          if (mLastHorizontalStyle!= UNKNOWN) {
              mFlow.setLastHorizontalStyle(mLastHorizontalStyle);
          }
  
          // General attributes of a widget
          applyBase();
      }
  }
  