/*
 * Copyright 2014-present Facebook, Inc.
 *
 * 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.facebook.litho;

import static com.facebook.litho.config.ComponentsConfiguration.DEFAULT_BACKGROUND_THREAD_PRIORITY;

import com.facebook.litho.config.DeviceInfoUtils;
import com.facebook.litho.config.LayoutThreadPoolConfiguration;

/** Configures a thread pool used for layout calculations. */
public class LayoutThreadPoolConfigurationImpl implements LayoutThreadPoolConfiguration {

  private int mCorePoolSize;
  private int mMaxPoolSize;
  private int mThreadPriority;

  public LayoutThreadPoolConfigurationImpl(int corePoolSize, int maxPoolSize, int threadPriority) {
    mCorePoolSize = corePoolSize;
    mMaxPoolSize = maxPoolSize;
    mThreadPriority = threadPriority;
  }

  @Override
  public int getCorePoolSize() {
    return mCorePoolSize;
  }

  @Override
  public int getMaxPoolSize() {
    return mMaxPoolSize;
  }

  @Override
  public int getThreadPriority() {
    return mThreadPriority;
  }

  public static class Builder {
    private boolean hasFixedSizePool;
    private int corePoolSize = 1;
    private int maxPoolSize = 1;
    private double corePoolSizeMultiplier = 1;
    private int corePoolSizeIncrement = 0;
    private double maxPoolSizeMultiplier = 1;
    private int maxPoolSizeIncrement = 0;
    private int threadPriority = DEFAULT_BACKGROUND_THREAD_PRIORITY;

    public Builder hasFixedSizePool(boolean hasFixedSizePool) {
      this.hasFixedSizePool = hasFixedSizePool;
      return this;
    }

    public Builder fixedSizePoolConfiguration(int corePoolSize, int maxPoolSize) {
      this.corePoolSize = corePoolSize;
      this.maxPoolSize = maxPoolSize;
      return this;
    }

    public Builder coreDependentPoolConfiguration(
        double corePoolSizeMultiplier,
        int corePoolSizeIncrement,
        double maxPoolSizeMultiplier,
        int maxPoolSizeIncrement) {
      this.corePoolSizeMultiplier = corePoolSizeMultiplier;
      this.corePoolSizeIncrement = corePoolSizeIncrement;
      this.maxPoolSizeMultiplier = maxPoolSizeMultiplier;
      this.maxPoolSizeIncrement = maxPoolSizeIncrement;
      return this;
    }

    public Builder threadPriority(int threadPriority) {
      this.threadPriority = threadPriority;
      return this;
    }

    public LayoutThreadPoolConfigurationImpl build() {
      if (hasFixedSizePool) {
        return new LayoutThreadPoolConfigurationImpl(corePoolSize, maxPoolSize, threadPriority);
      }

      int numProcessors = DeviceInfoUtils.getNumberOfCPUCores();

      if (numProcessors == DeviceInfoUtils.DEVICEINFO_UNKNOWN || numProcessors == 0) {
        numProcessors = 1;
        ComponentsReporter.emitMessage(
            ComponentsReporter.LogLevel.WARNING, "Could not read number of cores from device");
      }

      int procDepCorePoolSize =
          (int) Math.ceil(numProcessors * corePoolSizeMultiplier + corePoolSizeIncrement);
      int procDepMaxPoolSize =
          (int) Math.ceil(numProcessors * maxPoolSizeMultiplier + maxPoolSizeIncrement);

      // Safety net if we somehow try to set an invalid pool size, which can happen if we set the
      // size to 0 or the max is smaller than the core size.
      if (procDepCorePoolSize == 0) {
        procDepCorePoolSize = 1;
      }

      if (procDepMaxPoolSize < procDepCorePoolSize) {
        procDepMaxPoolSize = procDepCorePoolSize;
      }

      return new LayoutThreadPoolConfigurationImpl(
          procDepCorePoolSize, procDepMaxPoolSize, threadPriority);
    }
  }
}

@@ -731,58 +731,8 @@
 Y;%0A%0A
-import com.facebook.litho.config.DeviceInfoUtils;%0A
 impo
@@ -791,16 +791,16 @@
 ration;%0A
+
 %0A/** Con
@@ -1034,16 +1034,174 @@
 ority;%0A%0A
+  public LayoutThreadPoolConfigurationImpl(int corePoolSize, int maxPoolSize) %7B%0A    this(corePoolSize, maxPoolSize, DEFAULT_BACKGROUND_THREAD_PRIORITY);%0A  %7D%0A%0A
   public
@@ -1594,24 +1594,24 @@
 riority() %7B%0A
+
     return m
@@ -1633,2543 +1633,7 @@
 %0A  %7D
-%0A%0A  public static class Builder %7B%0A    private boolean hasFixedSizePool;%0A    private int corePoolSize = 1;%0A    private int maxPoolSize = 1;%0A    private double corePoolSizeMultiplier = 1;%0A    private int corePoolSizeIncrement = 0;%0A    private double maxPoolSizeMultiplier = 1;%0A    private int maxPoolSizeIncrement = 0;%0A    private int threadPriority = DEFAULT_BACKGROUND_THREAD_PRIORITY;%0A%0A    public Builder hasFixedSizePool(boolean hasFixedSizePool) %7B%0A      this.hasFixedSizePool = hasFixedSizePool;%0A      return this;%0A    %7D%0A%0A    public Builder fixedSizePoolConfiguration(int corePoolSize, int maxPoolSize) %7B%0A      this.corePoolSize = corePoolSize;%0A      this.maxPoolSize = maxPoolSize;%0A      return this;%0A    %7D%0A%0A    public Builder coreDependentPoolConfiguration(%0A        double corePoolSizeMultiplier,%0A        int corePoolSizeIncrement,%0A        double maxPoolSizeMultiplier,%0A        int maxPoolSizeIncrement) %7B%0A      this.corePoolSizeMultiplier = corePoolSizeMultiplier;%0A      this.corePoolSizeIncrement = corePoolSizeIncrement;%0A      this.maxPoolSizeMultiplier = maxPoolSizeMultiplier;%0A      this.maxPoolSizeIncrement = maxPoolSizeIncrement;%0A      return this;%0A    %7D%0A%0A    public Builder threadPriority(int threadPriority) %7B%0A      this.threadPriority = threadPriority;%0A      return this;%0A    %7D%0A%0A    public LayoutThreadPoolConfigurationImpl build() %7B%0A      if (hasFixedSizePool) %7B%0A        return new LayoutThreadPoolConfigurationImpl(corePoolSize, maxPoolSize, threadPriority);%0A      %7D%0A%0A      int numProcessors = DeviceInfoUtils.getNumberOfCPUCores();%0A%0A      if (numProcessors == DeviceInfoUtils.DEVICEINFO_UNKNOWN %7C%7C numProcessors == 0) %7B%0A        numProcessors = 1;%0A        ComponentsReporter.emitMessage(%0A            ComponentsReporter.LogLevel.WARNING, %22Could not read number of cores from device%22);%0A      %7D%0A%0A      int procDepCorePoolSize =%0A          (int) Math.ceil(numProcessors * corePoolSizeMultiplier + corePoolSizeIncrement);%0A      int procDepMaxPoolSize =%0A          (int) Math.ceil(numProcessors * maxPoolSizeMultiplier + maxPoolSizeIncrement);%0A%0A      // Safety net if we somehow try to set an invalid pool size, which can happen if we set the%0A      // size to 0 or the max is smaller than the core size.%0A      if (procDepCorePoolSize == 0) %7B%0A        procDepCorePoolSize = 1;%0A      %7D%0A%0A      if (procDepMaxPoolSize %3C procDepCorePoolSize) %7B%0A        procDepMaxPoolSize = procDepCorePoolSize;%0A      %7D%0A%0A      return new LayoutThreadPoolConfigurationImpl(%0A          procDepCorePoolSize, procDepMaxPoolSize, threadPriority);%0A    %7D%0A  %7D
 %0A%7D%0A

Clean up LayoutThreadPoolConfigurationImpl