/* LanguageTool, a natural language style checker
 * Copyright (C) 2020 Daniel Naber (http://www.danielnaber.de)
 *
 * 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.en;

import org.jetbrains.annotations.Nullable;
import org.languagetool.AnalyzedTokenReadings;
import org.languagetool.rules.RuleMatch;
import org.languagetool.rules.patterns.RuleFilter;

import java.util.HashMap;
import java.util.Map;

/**
 * Filter that maps suggestion from adverb to adjective.
 * Also see https://www.ef.com/wwen/english-resources/english-grammar/forming-adverbs-adjectives/
 * @since 4.9
 */
public class AdverbFilter extends RuleFilter {

  private final Map<String,String> adverb2Adj = new HashMap<String, String>() {{
    // irregular ones:
    put("well", "good");
    put("fast", "fast");
    put("hard", "hard");
    put("late", "late");
    put("early", "early");
    put("daily", "daily");
    put("straight", "straight");
    // regular ones:
    put("simply", "simple");
    put("cheaply", "cheap");
    put("quickly", "quick");
    put("slowly", "slow");
    put("easily", "easy");
    put("angrily", "angry");
    put("happily", "happy");
    put("luckily", "lucky");
    put("terribly", "terrible");
    put("tragically", "tragic");
    put("economically", "economic");
    put("greatly", "great");
    put("highly", "high");
    put("generally", "general");
    put("differently", "different");
    put("rightly", "right");
    put("largely", "large");
    put("really", "real");
    put("philosophically", "philosophical");
    put("directly", "direct");
    put("clearly", "clear");
    put("merely", "mere");
    put("exactly", "exact");
    put("recently", "recent");
    put("rapidly", "rapid");
    put("suddenly", "sudden");
    put("extremely", "extreme");
    put("properly", "proper");
    put("politically", "political");
    put("probably", "probable");
    put("self-consciously", "self-conscious");
    put("successfully", "successful");
    put("unusually", "unusual");
    put("obviously", "obvious");
    put("currently", "current");
    put("residentially", "residential");
    put("fully", "full");
    put("accidentally", "accidental");
    put("medicinally", "medicinal");
    put("automatically", "automatic");
    put("completely", "complete");
    put("chronologically", "chronological");
    put("accurately", "accurate");
    put("necessarily", "necessary");
    put("temporarily", "temporary");
    put("significantly", "significant");
    put("hastily", "hasty");
    put("immediately", "immediate");
    put("rarely", "rare");
    put("totally", "total");
    put("literally", "literal");
    put("gently", "gentle");
    put("finally", "final");
    put("increasingly", "increasing");
    put("decreasingly", "decreasing");
    put("considerably", "considerable");
    put("effectively", "effective");
    put("briefly", "brief");
    put("exceedingly", "exceeding");
    put("physically", "physical");
    put("enthusiastically", "enthusiastic");
    put("incredibly", "incredible");
    put("permanently", "permanent");
    put("entirely", "entire");
    put("surely", "sure");
    put("positively", "positive");
    put("negatively", "negative");
    put("devastatingly", "devastating");
    put("relatively", "relative");
    put("absolutely", "absolute");
    put("socially", "social");
    put("industriously", "industrious");
    put("solely", "sole");
    put("asynchronously", "asynchronous");
    put("fortunately", "fortunate");
    put("unfortunately", "unfortunate");
    put("ideally", "ideal");
    put("privately", "private");
    put("unreasonably", "unreasonable");
    put("personally", "personal");
    put("basically", "basic");
    put("definitely", "definite");
    put("potentially", "potential");
    put("manually", "manual");
    put("continuously", "continuous");
    put("sadly", "sad");
    put("eventually", "eventual");
    put("possibly", "possible");
    put("visually", "visual");
    put("predominantly", "predominant");
    put("predominately", "predominant"); // special case
    put("quietly", "quiet");
    put("slightly", "slight");
    put("cleverly", "clever");
    put("roughly", "rough");
    put("environmentally", "environmental");
    put("geographically", "geographical");
    put("usually", "usual");
    put("normally", "normal");
    put("deliciously", "delicious");
    put("steadily", "steady");
    put("actively", "active");
    put("schematically", "schematic");
    put("mindfully", "mindful");
    put("statistically", "statistical");
    put("culturally", "cultural");
    put("vicariously", "vicarious");
    put("vividly", "vivid");
    put("partially", "partial");
    // put("unduly", "undue");
    put("seriously", "serious");
    put("non-verbally", "non-verbal");
    put("nonverbally", "nonverbal");
    put("verbally", "verbal");
    put("shortly", "short");
    put("mildly", "mild");
    put("secretly", "secret");
    put("especially", "especial");
    put("specially", "special");
    put("previously", "previous");
    put("whitely", "white");
    put("traditionally", "traditional");
    put("individually", "individual");
    put("carefully", "careful");
    put("essentially", "essential");
    put("originally", "original");
    put("alarmingly", "alarming");
    put("newly", "new");
    put("wrongfully", "wrongful");
    put("structurally", "structural");
    put("globally", "global");
    put("pacifically", "pacific");
    put("seemingly", "seeming");
    put("seamlessly", "seamless");
    put("sustainably", "sustainable");
    put("momentarily", "momentary");
    put("coldly", "cold");
    put("densely", "dense");
    put("grimly", "grim");
    put("calmly", "calm");
    put("racially", "racial");
    put("widely", "wide");
    put("heavily", "heavy");
    put("authentically", "authentic");
    put("honestly", "honest");
    put("desperately", "desperate");
    put("immensely", "immense");
    put("apparently", "apparent");
    put("straightforwardly", "straightforward");
    put("anatomically", "anatomical");
    put("uniquely", "unique");
    put("systemically", "systemic");
    put("jokily", "jokey");
    put("critically", "critical");
    put("equally", "equal");
    put("strongly", "strong");
    put("purposely", "intentional");
    put("thoroughly", "thorough");
    put("outwardly", "outward");
    put("horizontally", "horizontal");
    put("vertically", "vertical");
    put("technically", "technical");
    put("swiftly", "swift");
    put("accessibly", "accessible");
    put("occasionally", "occasional");
    put("specifically", "specific");
    put("subtly", "subtle");
    put("actually", "actual");
    put("particularly", "particular");
    put("gloomily", "gloomy");
    put("nicely", "nice");
    put("progressively", "progressive");
    put("genuinely", "genuine");
    put("characteristically", "characteristic");
    put("deeply", "deep");
    put("spiritually", "spiritual");
    put("purely", "pure");
    put("satisfyingly", "satisfying");
    put("indolently", "indolent");
    put("obliquely", "oblique");
    put("preferably", "preferable");
    put("oddly", "odd");
    put("professionally", "professional");
    put("indispensably", "indispensable");
    put("dispensably", "dispensable");
    put("consistently", "consistent");
    put("truly", "true");
    put("commonly", "common");
    put("safely", "safe");
    put("evolutionarily", "evolutionary");
    put("internally", "internal");
    put("magically", "magical");
    put("annually", "annual");
    put("brightly", "bright");
    put("officially", "official");
    put("inofficially", "inofficial");
    put("perfectly", "perfect");
    put("overly", "over");
    put("tropically", "tropical");
    put("brilliantly", "brilliant");
    put("exclusively", "exclusive");
    put("commercially", "commercial");
    put("mischievously", "mischievous");
    put("weirdly", "weird");
    put("routinely", "routine");
    put("gruffly", "gruff");
    put("naturally", "natural");
    put("lightly", "light");
    put("haphazardly", "haphazard");
    put("lovingly", "loving");
    put("sagely", "sage");
    put("systematically", "systematical");
    put("academically", "academical");
    put("jokingly", "joking");
    put("primarily", "primary");
    put("secondarily", "secondary");
    put("peacefully", "peaceful");
    put("thankfully", "thankful");
    put("reliably", "reliable");
    put("unreliably", "unreliable");
    put("infinitesimally", "infinitesimal");
    put("hugely", "huge");
    put("strictly", "strict");
    put("morally", "moral");
    put("involuntarily", "involuntary");
    put("voluntarily", "voluntary");
    put("vanishingly", "vanishing");
    put("typically", "typical");
    put("playfully", "playful");
    put("wonderfully", "wonderful");
    put("roguishly", "roguish");
    put("emotionally", "emotional");
    put("efficiently", "efficient");
    put("unkindly", "unkind");
    put("mentally", "mental");
    put("credibly", "credible");
    put("seductively", "seductive");
    put("rashly", "rash");
    put("outwards", "outward");
    put("periodically", "periodical");
    put("comparatively", "comparative");
    put("confidentially", "confidential");
    put("dominantly", "dominant");
    put("forcibly", "forcible");
    put("formerly", "former");
    put("financially", "financial");
    put("urgently", "urgent");
    put("inherently", "inherent");
    put("historically", "historical");
    put("tightly", "tight");
    put("greedily", "greedy");
    put("fluently", "fluent");
    put("ordinarily", "ordinary");
    put("inevitably", "inevitable");
    put("partly", "partial");
    put("liquidly", "liquid");
    put("supremely", "supreme");
    put("initially", "initial");
    put("unjustly", "unjust");
    put("justly", "just");
    put("plausibly", "plausible");
    put("amiably", "amiable");
    put("massively", "massive");
    put("lowly", "low");
    put("notoriously", "notorious");
    put("meaningfully", "meaningful");
    put("approximately", "approximate");
    put("extraordinarily", "extraordinary");
    put("warmly", "warm");
    put("nearly", "near");
    put("strategically", "strategical");
    put("endlessly", "endless");
    put("virtually", "virtual");
    put("regularly", "regular");
    put("deliberately", "deliberate");
    put("reasonably", "reasonable");
    put("similarly", "similar");
    put("flexibly", "flexible");
    put("softly", "soft");
    put("responsibly", "responsible");
    put("irresponsibly", "irresponsible");
    put("sweetly", "sweet");
    put("comfortably", "comfortable");
    put("uncomfortably", "uncomfortable");
    put("intricately", "intricate");
    put("unnecessarily", "unnecessary");
    put("obstinately", "obstinate");
    put("reportedly", "reported");
    put("loosely", "loose");
    put("profusely", "profuse");
    put("mortally", "mortal");
    put("dynamically", "dynamical");
    put("illegally", "illegal");
    put("legally", "legal");
    put("undoubtedly", "undoubted");
    put("humanly", "human");
    put("likewise", "similar"); // special case
    put("intrinsically", "intrinsic");
    put("substantially", "substantial");
    put("suspiciously", "suspicious");
    put("generationally", "generational");
    put("loudly", "loud");
    put("moderately", "moderate");
    put("gravely", "grave");
    put("temporally", "temporal");
    put("digitally", "digital");
    put("finely", "fine");
    put("respectfully", "respectful");
    put("questioningly", "questioning");
    put("diagonally", "diagonal");
    put("additionally", "additional");
    put("sexually", "sexual");
    put("remarkably", "remarkable");
    put("acutely", "acute");
    put("linearly", "linear");
    put("perfunctorily", "perfunctory");
    put("unbelievably", "unbelievable");
    put("merrily", "merry");
    put("beneath", "below"); // special case
    put("lest", "least"); // special case
    put("either", "other"); // special case
    put("nasally", "nasal");
    put("concretely", "concrete");
    put("intuitively", "intuitive");
    put("please", "pleasing");
    put("intermediately", "intermediate");
    put("powerfully", "powerful");
    put("fairly", "fair");
    put("wholly", "whole");
    put("keenly", "keen");
    put("unconsciously", "unconscious");
    put("consciously", "conscious");
    put("humanely", "humane");
    put("honorably", "honorable");
    put("rudely", "rude");
    put("incorrectly", "incorrect");
    put("correctly", "correct");
    put("mistakenly", "mistaken");
    put("wrongly", "wrong");
    put("morosely", "morose");
    put("worryingly", "worrying");
    put("drastically", "drastical");
    put("willingly", "willing");
    put("additively", "additive");
    put("drolly", "droll");
    put("statically", "statical");
    put("hopefully", "hopeful");
    put("untruthfully", "untruthful");
    put("truthfully", "truthful");
    put("attractively", "attractive");
    put("supposedly", "supposed");
    put("overwhelmingly", "overwhelming");
    put("imperfectly", "imperfect");
    put("deftly", "deft");
    put("wildly", "wild");
    put("sheepishly", "sheepish");
    put("hotly", "hot");
    put("genetically", "genetic");
    put("inexplicably", "inexplicable");
    put("explicably", "explicable");
    put("domestically", "domestical");
    put("invisibly", "invisible");
    put("visibly", "visible");
    put("noteworthily", "noteworthy");
    put("unexpectably", "unexpectable");
    put("expectably", "expectable");
    put("foreseeably", "foreseeable");
    put("unforeseeably", "unforeseeable");
    put("distinctly", "distinct");
    put("unequivocally", "unequivocal");
    put("signally", "signal");
    put("medically", "medical");
    put("certainly", "certain");
    put("beautifully", "beautiful");
    put("firmly", "firm");
    put("electrically", "electrical");
    put("gradually", "gradual");
    put("grossly", "gross");
    put("memorably", "memorable");
    put("unmemorably", "unmemorable");
    put("shelly", "shell");
    put("strangely", "strange");
    put("unhealthily", "unhealthy");
    put("healthily", "healthy");
    put("harshly", "harsh");
    put("proudly", "proud");
    put("lately", "late");
    put("remotely", "remote");
    put("longly", "long");
    put("politely", "polite");
    put("ethically", "ethical");
    put("noticeably", "noticeable");
    put("unnoticeably", "unnoticeable");
    put("consequently", "consequent");
    put("snugly", "snug");
    put("mainly", "main");
    put("popularly", "popular");
    put("improperly", "improper");
    put("deliverly", "delivery");
    put("rushingly", "rushing");
    put("gravitationally", "gravitational");
    put("cruelly", "cruel");
    put("optimally", "optimal");
    put("fictionally", "fictional");
    put("manageably", "manageable");
    put("unmanageably", "unmanageable");
    put("fashionably", "fashionable");
    put("secondly", "second");
    put("thirdly", "third");
    put("curtly", "curt");
    put("secretively", "secretive");
    put("surprisingly", "surprising");
    put("sociologically", "sociological");
    put("severely", "severe");
    put("ruffianly", "ruffian");
    put("bigly", "big");
    put("frequently", "frequent");
    put("irrationally", "irrational");
    put("rationally", "rational");
    put("riotously", "riotous");
    put("excruciatingly", "excruciating");
    put("intensively", "intensive");
    put("separately", "separate");
    put("favorably", "favorable");
    put("favourably", "favourable");
    put("unfavorably", "unfavorable");
    put("unfavourably", "unfavourable");
    put("fittingly", "fitting");
    put("orally", "oral");
    put("jointly", "joint");
    put("methodically", "methodical");
    put("ecologically", "ecological");
    put("irrepressibly", "irrepressible");
    put("repressibly", "repressible");
    put("heartily", "hearty");
    put("smoothly", "smooth");
    put("dreamily", "dreamy");
    put("indirectly", "indirect");
    put("fascinatingly", "fascinating");
    put("scientifically", "scientific");
    put("unhappily", "unhappy");
    put("publicly", "public");
    put("healthfully", "healthful");
    put("uncharacteristically", "uncharacteristic");
    put("genially", "genial");
    put("ineludibly", "ineludible");
    put("tenderly", "tender");
    put("arguably", "arguable");
    put("comparably", "comparable");
    put("procedurally", "procedural");
    put("interchangeably", "interchangeable");
    put("conceivably", "conceivable");
    put("jokily", "joking");
    put("resignedly", "resigned");
    put("vehemently", "vehement");
    put("horribly", "horrible");
    put("teasingly", "teasing");
    put("figuratively", "figurative");
    put("excitingly", "exciting");
    put("haltingly", "halting");
    put("phonetically", "phonetic");
    put("proverbially", "proverbial");
    put("informally", "informal");
    put("cozily", "cozy");
    put("cosily", "cosy");
    put("constantly", "constant");
    put("rightfully", "rightful");
    put("reluctantly", "reluctant");
    put("externally", "external");
    put("intellectually", "intellectual");
    put("dramatically", "dramatic");
    put("freshly", "fresh");
    put("casually", "casual");
    put("unevenly", "uneven");
    put("enormously", "enormous");
    put("callously", "callous");
    put("imperiously", "imperious");
    put("messily", "messy");
    put("alternatively", "alternative");
    put("gladly", "glad");
    put("adversely", "adverse");
    put("petulantly", "petulant");
    put("shakily", "shaky");
    put("menacingly", "menacing");
    put("consensually", "consensual");
    put("bitterly", "bitter");
    put("terminally", "terminal");
    put("faintly", "faint");
    put("brusquely", "brusque");
    put("humbly", "humble");
    put("promptly", "prompt");
    put("identically", "identical");
    put("militarily", "military");
    put("neatly", "neat");
    put("insanely", "insane");
    put("analytically", "analytical");
    put("firstly", "first");
    put("secondly", "second");
    put("twice", "second"); // special case
    // TODO: add more or maybe use https://github.com/simplenlg/simplenlg?
    //put("", "");
  }};

  @Nullable
  @Override
  public RuleMatch acceptRuleMatch(RuleMatch match, Map<String, String> arguments, int patternTokenPos, AnalyzedTokenReadings[] patternTokens) {
    String adverb = arguments.get("adverb");
    String noun = arguments.get("noun");
    String adjective = adverb2Adj.get(adverb);
    if (adjective != null && !adjective.equals(adverb)) {
      // we can't simply cut off "ly" because of cases like "simply" -> "simple" etc.
      match.setSuggestedReplacement(adjective + " " + noun);
    }
    return match;
  }
}
