/*
 * Copyright 2013-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.buck.util.unit;

import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableMap;

import java.math.BigDecimal;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public enum SizeUnit {
  BYTES(0),
  KILOBYTES(1),
  MEGABYTES(2),
  GIGABYTES(3),
  TERABYTES(4);

  private final int ordinal;

  private SizeUnit(int ordinal) {
    this.ordinal = ordinal;
  }

  public int getOrdinal() {
    return ordinal;
  }

  private static long multiplyByByteOrderOfMagnitude(double size, int magnitude) {
    if (magnitude == 0) {
      return (long) size;
    } else if (magnitude > 0) {
      return BigDecimal.valueOf(size).multiply(BigDecimal.valueOf(1024).pow(magnitude)).longValue();
    } else {
      return BigDecimal.valueOf(size).divide(
          BigDecimal.valueOf(1024).pow(-1 * magnitude)).longValue();
    }
  }

  private static ImmutableMap<String, SizeUnit> SHORT_TO_CODE =
      ImmutableMap.<String, SizeUnit>builder()
        .put("b", BYTES)
        .put("kb", KILOBYTES)
        .put("kilobytes", KILOBYTES)
        .put("mb", MEGABYTES)
        .put("megabytes", MEGABYTES)
        .put("gb", GIGABYTES)
        .put("gigabytes", GIGABYTES)
        .put("tb", TERABYTES)
        .put("terabytes", TERABYTES)
        .build();

  private static Pattern SIZE_PATTERN = Pattern.compile("([\\d]+(?:\\.[\\d]+)?)\\s*((?:" +
      Joiner.on(")|(?:").join(SHORT_TO_CODE.keySet()) + "))",
      Pattern.CASE_INSENSITIVE);

  /**
   * Parses a string that represents a size into the number of bytes represented by that string.
   */
  public static long parseBytes(String input) throws NumberFormatException {
    Matcher matcher = SIZE_PATTERN.matcher(input);
    if (matcher.find()) {
      String number = matcher.group(1);
      SizeUnit sizeUnit = SHORT_TO_CODE.get(matcher.group(2).toLowerCase());
      if (sizeUnit != null) {
        try {
          double value = Double.parseDouble(number);
          return sizeUnit.toBytes(value);
        } catch (NumberFormatException e) {
          // If the number was so large as to overflow Long.MAX_VALUE, return LONG.MAX_VALUE.
          return Long.MAX_VALUE;
        }
      }
    }
    throw new NumberFormatException(String.format("%s is not a valid file size", input));
  }

  public long toBytes(double size) {
    return multiplyByByteOrderOfMagnitude(size, getOrdinal() - BYTES.getOrdinal());
  }

  public long toKilobytes(double size) {
    return multiplyByByteOrderOfMagnitude(size, getOrdinal() - KILOBYTES.getOrdinal());
  }

  public long toMegabytes(double size) {
    return multiplyByByteOrderOfMagnitude(size, getOrdinal() - MEGABYTES.getOrdinal());
  }

  public long toGigabytes(double size) {
    return multiplyByByteOrderOfMagnitude(size, getOrdinal() - GIGABYTES.getOrdinal());
  }

  public long toTerabytes(double size) {
    return multiplyByByteOrderOfMagnitude(size, getOrdinal() - TERABYTES.getOrdinal());
  }
}
