/*
 *  LanguageTool, a natural language style checker
 *  * Copyright (C) 2018 Fabian Richter
 *  *
 *  * This library is free software; you can redistribute it and/or
 *  * modify it under the terms of the GNU Lesser General Public
 *  * License as published by the Free Software Foundation; either
 *  * version 2.1 of the License, or (at your option) any later version.
 *  *
 *  * This library is distributed in the hope that it will be useful,
 *  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  * Lesser General Public License for more details.
 *  *
 *  * You should have received a copy of the GNU Lesser General Public
 *  * License along with this library; if not, write to the Free Software
 *  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
 *  * USA
 *
 */
package org.languagetool.rules.de;

import org.languagetool.rules.AbstractUnitConversionRule;
import org.languagetool.rules.Example;

import java.math.RoundingMode;
import java.text.NumberFormat;
import java.util.Locale;
import java.util.ResourceBundle;

import static tech.units.indriya.unit.Units.*;

/**
 * @since 4.3
 */
public class UnitConversionRule extends AbstractUnitConversionRule {

  private final NumberFormat format;

  public UnitConversionRule(ResourceBundle messages) {
    super(messages);
    format = NumberFormat.getNumberInstance(Locale.GERMANY);
    format.setMaximumFractionDigits(2);
    format.setRoundingMode(RoundingMode.HALF_UP);
    addExamplePair(Example.wrong("Ich bin <marker>6 Fuß</marker> groß."),
                   Example.fixed("Ich bin <marker>6 Fuß (1,83 m)</marker> groß."));

    addUnit("Kilo(gramm)?", KILOGRAM, "Kilogramm", 1, true);
    addUnit("Gramm", KILOGRAM, "Gramm", 1e-3, true);
    addUnit("Tonnen?", KILOGRAM, "Tonnen", 1e3, true);
    addUnit("Pfund", POUND, "Pfund", 1, false);

    addUnit("Meilen?", MILE, "Meile", 1, false);
    addUnit("Yard", YARD, "Yard", 1, false);
    addUnit("Fuß", FEET, "Fuß", 1, false);
    addUnit("Zoll", INCH, "Zoll", 1, false);

    addUnit("(Kilometer pro Stunde|Stundenkilometer)", KILOMETRE_PER_HOUR, "Kilometer pro Stunde", 1, true);
    addUnit("Meilen pro Stunde", MILE.divide(HOUR), "Meilen pro Stunde", 1, false);

    addUnit("Meter", METRE, "Meter", 1, true);
    addUnit("Kilometer", METRE, "Kilometer", 1e3, true);
    addUnit("Dezimeter", METRE, "Dezimeter", 1e-1, false); // metric, but should not be suggested
    addUnit("Zentimeter", METRE, "Zentimeter", 1e-2, true);
    addUnit("Millimeter", METRE, "Millimeter", 1e-3, true);
    addUnit("Mikrometer", METRE, "Mikrometer", 1e-6, true);
    addUnit("Nanometer", METRE, "Nanometer", 1e-9, true);
    addUnit("Pikometer", METRE, "Pikometer", 1e-12, true);
    addUnit("Femtometer", METRE, "Femtometer", 1e-15, true);

    addUnit("Quadratmeter", SQUARE_METRE, "Quadratmeter", 1, true);
    addUnit("Hektar", SQUARE_METRE, "Hektar", 1e4, true);
    addUnit("Ar", SQUARE_METRE, "Ar", 1e2, true);
    addUnit("Quadratkilometer", SQUARE_METRE,  "Quadratkilometer",  1e6, true);
    addUnit("Quadratdezimeter", SQUARE_METRE,  "Quadratdezimeter",  1e-2, false/*true*/); // Metric, but not commonly used
    addUnit("Quadratzentimeter", SQUARE_METRE, "Quadratzentimeter", 1e-4, true);
    addUnit("Quadratmillimeter", SQUARE_METRE, "Quadratmillimeter", 1e-6, true);
    addUnit("Quadratmikrometer", SQUARE_METRE, "Quadratmikrometer", 1e-12, true);
    addUnit("Quadratnanometer", SQUARE_METRE,  "Quadratnanometer",  1e-18, true);

    addUnit("Kubikmeter", CUBIC_METRE,     "Kubikmeter",      1, true);
    addUnit("Kubikkilometer", CUBIC_METRE, "Kubikkilometer",  1e9, true);
    addUnit("Kubikdezimeter", CUBIC_METRE, "Kubikdezimeter",  1e-3, false/*true*/); // Metric, but not commonly used
    addUnit("Kubikzentimeter", CUBIC_METRE,"Kubikzentimeter", 1e-6, true);
    addUnit("Kubikmillimeter", CUBIC_METRE,"Kubikmillimeter", 1e-9, true);
    addUnit("Kubikmikrometer", CUBIC_METRE,"Kubikmikrometer", 1e-18, true);
    addUnit("Kubiknanometer", CUBIC_METRE, "Kubiknanometer",  1e-27, true);

    addUnit("Liter", LITRE, "Liter", 1, true);
    addUnit("Milliliter", LITRE, "Milliliter", 1e-3, true);

    addUnit( "(?:Grad)? Fahrenheit", FAHRENHEIT, "Grad Fahrenheit", 1, false);
    addUnit( "(?:Grad)? Celsius", CELSIUS, "Grad Celsius", 1, true);
  }

  @Override
  public String getId() {
    return "EINHEITEN_METRISCH";
  }

  @Override
  public String getDescription() {
    return "Schlägt vor oder überprüft Angaben des metrischen Äquivalentes bei bestimmten Maßeinheiten.";
  }

  @Override
  protected String getMessage(Message message) {
    switch(message) {
      case CHECK:
        return "Diese Umrechnung scheint falsch zu sein. Wollen Sie sie automatisch korrigieren lassen?";
      case SUGGESTION:
        return "Wollen Sie eine Umwandlung ins metrische System automatisch hinzufügen?";
      case CHECK_UNKNOWN_UNIT:
        return "Die in dieser Umrechnung verwendete Einheit wurde nicht erkannt.";
      case UNIT_MISMATCH:
        return "Diese Einheiten sind nicht kompatibel.";
      default:
        throw new RuntimeException("Unknown message type: " + message);
    }
  }

  @Override
  protected String getShortMessage(Message message) {
    switch(message) {
      case CHECK:
        return "Falsche Umrechnung. Automatisch korrigieren?";
      case SUGGESTION:
        return "Metrisches Äquivalent hinzufügen?";
      case CHECK_UNKNOWN_UNIT:
        return "Unbekannte Einheit.";
      case UNIT_MISMATCH:
        return "Inkompatible Einheiten.";
      default:
        throw new RuntimeException("Unknown message type: " + message);
    }
  }

  @Override
  protected NumberFormat getNumberFormat() {
    return format;
  }

}
