content: /**
   *   Copyright 2012-2019 Wicked Charts (http://github.com/adessoAG/wicked-charts)
   *
   *   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 de.adesso.wickedcharts.highcharts.options.util;
  
  import de.adesso.wickedcharts.highcharts.options.*;
  import de.adesso.wickedcharts.highcharts.options.series.Point;
  import de.adesso.wickedcharts.highcharts.options.series.Series;
  
  import java.util.ArrayList;
  import java.util.List;
  
  public class OptionsUtil {
  
      private static OptionsUtil INSTANCE = new OptionsUtil();
  
      public static OptionsUtil getInstance() {
          return INSTANCE;
      }
  
      private OptionsUtil() {
  
      }
  
      /**
       * Copies the renderTo configuration from one {@link Options} object to
       * another. Null-safe.
       *
       * @param from Object to copy from
       * @param to Object to copy to
       */
      public void copyRenderTo(final Options from, final Options to) {
          if (to.getChartOptions() == null) {
              to.setChartOptions(new ChartOptions());
          }
          to.getChartOptions().setRenderTo(from.getChartOptions().getRenderTo());
      }
  
      /**
       * Null-safe setter for the renderTo configuration.
       *
       * @param options the Options object to set the renderTo of
       * @param renderTo the render target
       */
      public void setRenderTo(final Options options, final String renderTo) {
          if (options.getChartOptions() == null) {
              options.setChartOptions(new ChartOptions());
          }
          options.getChartOptions().setRenderTo(renderTo);
      }
  
      /*
       * Null-safe setter for the chart.events.load configuration.
       */
      public void setChartEventsLoad(final Options options, final Function function) {
          if (options.getChartOptions() == null) {
              options.setChartOptions(new ChartOptions());
          }
          if (options.getChartOptions().getEvents() == null) {
              options.getChartOptions().setEvents(new Events());
          }
          if (options.getChartOptions().getEvents().getLoad() == null) {
              options.getChartOptions().getEvents().setLoad(function);
          }
      }
  
      /**
       * Checks if the specified Options object needs the javascript file
       * "highcharts-more.js" to work properly. This method can be called by GUI
       * components to determine whether the javascript file has to be included in
       * the page or not.
       *
       * @param options the {@link Options} object to analyze
       * @return true, if "highcharts-more.js" is needed to render the options,
       * false if not
       */
      public static boolean needsHighchartsMoreJs(final Options options) {
          return hasPolar(options) || hasChartTypeNeedingMoreJs(options);
      }
  
      /**
       * Checks if the specified Options object needs the javascript file
       * "funnel.js" to work properly. This method can be called by GUI
       * components to determine whether the javascript file has to be included in
       * the page or not.
       *
       * @param options the {@link Options} object to analyze
       * @return true, if "funnel.js" is needed to render the options,
       * false if not
       */
      public static boolean needsFunnelJs(final Options options) {
          return
                  options.getChart() != null &&
                          (options.getChart().getType() == SeriesType.FUNNEL ||
                                  options.getChart().getType() == SeriesType.PYRAMID);
      }
  
      /**
       * Checks if the specified Options object needs the javascript file
       * "heatmap.js" to work properly. This method can be called by GUI
       * components to determine whether the javascript file has to be included in
       * the page or not.
       *
       * @param options the {@link Options} object to analyze
       * @return true, if "funnel.js" is needed to render the options,
       * false if not
       */
      public static boolean needsHeatmapJs(final Options options) {
          return
                  options.getChart() != null &&
                          (options.getChart().getType() == SeriesType.HEATMAP);
      }
  
      /**
       * Checks if the specified Options object needs the javascript file
       * "exporting.js" to work properly. This method can be called by GUI
       * components to determine whether the javascript file has to be included in
       * the page or not.
       *
       * @param options the {@link Options} object to analyze
       * @return true, if "exporting.js" is needed to render the options, false if
       * not
       */
      public static boolean needsExportingJs(final Options options) {
          // when no ExportingOptions are set, they are enabled by default, hence
          // return true when they are null
          return options.getExporting() == null
                  || (options.getExporting().getEnabled() != null && options.getExporting().getEnabled());
      }
  
      private static boolean hasPolar(final Options options) {
          return options.getChartOptions() != null && options.getChartOptions().getPolar() != null
                  && options.getChartOptions().getPolar();
      }
  
      private static boolean hasChartTypeNeedingMoreJs(final Options options) {
          if (options.getChartOptions() != null && options.getChartOptions().getType() != null
                  && options.getChartOptions().getType().getChartType() == ChartType.ADVANCED) {
              return true;
          }
          if (options.getSeries() != null) {
              for (Series<?> series : options.getSeries()) {
                  if (series.getType() != null && series.getType().getChartType() == ChartType.ADVANCED) {
                      return true;
                  }
              }
          }
          return false;
      }
  
      /**
       * Retrieves the {@link Series} object with the given wickedChartsId from the
       * given {@link Options} object. Returns null if a Series with the given ID
       * does not exist.
       *
       * @param options Chartoptions
       *
       * @param wickedChartsId corresponding ID
       *
       * @return Series object
       */
      public static Series<?> getSeriesWithWickedChartsId(final Options options, final int wickedChartsId) {
          for (Series<?> series : options.getSeries()) {
              if (series.getWickedChartsId() == wickedChartsId) {
                  return series;
              }
          }
          return null;
      }
  
      /**
       * Retrieves the {@link Point} object with the given wickedChartsId from the
       * given {@link Options} object. Returns null if a Point with the given ID
       * does not exist.
       *
       * @param options Chartoptions
       *
       * @param wickedChartsId corresponding ID
       *
       * @return Point object
       */
      public static Point getPointWithWickedChartsId(final Options options, final int wickedChartsId) {
          for (Series<?> series : options.getSeries()) {
              for (Object object : series.getData()) {
                  if (!(object instanceof Point)) {
                      break;
                  } else {
                      Point point = (Point) object;
                      if (point.getWickedChartsId() == wickedChartsId) {
                          return point;
                      }
                  }
              }
          }
          return null;
      }
  
      public static Axis getAxisWithWickedChartsId(final Options options, final int wickedChartsId) {
          List<Axis> allAxes = new ArrayList<Axis>();
          allAxes.addAll(options.getxAxis());
          allAxes.addAll(options.getyAxis());
  
          for (Axis axis : allAxes) {
              if (axis.getWickedChartsId() == wickedChartsId) {
                  return axis;
              }
          }
          return null;
      }
  
      /**
       * Returns the (0-based) index of the series with the given wickedChartsId or
       * null.
       *
       * @param options        the options in which to search
       * @param wickedChartsId the wickedChartsId of the series
       * @return the index of the series with the given id. Returns 0 if no series
       * was found.
       */
      public static int getSeriesIndex(final Options options, final int wickedChartsId) {
          int index = 0;
          if (options.getSeries() == null) {
              throw new IllegalStateException("The given Options object does not contain any series!");
          }
          for (Series<?> series : options.getSeries()) {
              if (series.getWickedChartsId() == wickedChartsId) {
                  return index;
              }
              index++;
          }
          return 0;
      }
  }
  