import i18next, { TFunction } from 'i18next';

function basicUsage(t: TFunction) {
  t('friend');
  t`friend`;
  t(['friend', 'tree']);
  t('friend', { myVar: 'someValue' });
  t(['friend', 'tree'], { myVar: 'someValue' });
}

function overloadedUsage(t: TFunction) {
  t('friend', 'test {{myVar}}', { myVar: 'someValue' });
  t(['friend', 'tree'], 'test {{myVar}}', { myVar: 'someValue' });
}

function returnCasts(t: TFunction) {
  const s: string = t('friend'); // same as <string>
  const s2: string = t`friend`;
  // @ts-expect-error
  const s3: string = t('friend', { returnObjects: true });
  const o: object = t('friend', { returnObjects: true });
  const sa: string[] = t('friend', { returnObjects: true });
  const oa: object[] = t('friend', { returnObjects: true });
}

function defautValue(t: TFunction) {
  t('translation:test', { defaultValue: 'test_en' });
  t('translation:test', { defaultValue: 'test_en', count: 1 });
  t('translation:test', {
    defaultValue_other: 'test_en_plural',
    defaultValue_one: 'test_en',
    count: 10,
  });

  // string (only) default value as second arg
  //  https://www.i18next.com/translation-function/essentials#passing-a-default-value
  //  https://github.com/i18next/i18next/blob/master/src/Translator.js#L66
  t('translation:test', 'test_en');
}

function callsMethodWithOptionalNullArg(t: TFunction) {
  function displayHint(hint?: string | null) {
    return String(hint);
  }
  displayHint(t('friend'));
}

function callsMethodWithRequiredNullArg(t: TFunction) {
  function displayHint(hint: string | null) {
    return String(hint);
  }
  displayHint(t('friend'));
}

function callsMethodWithRequiredArg(t: TFunction) {
  function displayHint(hint: string) {
    return String(hint);
  }
  displayHint(t('friend'));
}

function arrayKey(t: TFunction) {
  const error404 = '404';
  t([`error.${error404}`, 'error.unspecific']); // -> "The page was not found"

  const error502 = '502';
  t([`error.${error502}`, 'error.unspecific']); // -> "Something went wrong"
}

function stringKey(t: TFunction) {
  t('No one says a key can not be the fallback.');
  // -> "Niemand sagt ein key kann nicht als Ersatz dienen."

  t('This will be shown if the current loaded translations to not have this.');
  // -> "This will be shown if the current loaded translations to not have this."
}

function interpolation(t: TFunction) {
  // key = 'hello {{what}}'
  t('key', { what: i18next.format('world', 'uppercase') }); // -> hello WORLD

  t('key', { what: 'i18next', how: 'great' });

  const author = {
    name: 'Jan',
    github: 'jamuhl',
  };
  t('key', { author });

  t('keyEscaped', { myVar: '<img />' });
  // -> "no danger &lt;img &#x2F;&gt;"

  t('keyUnescaped', { myVar: '<img />' });
  // -> "dangerous <img />"

  t('keyEscaped', {
    myVar: '<img />',
    interpolation: { escapeValue: false },
  });
  // -> "no danger <img />" (obviously could be dangerous)

  t('key', { count: 0 }); // -> "items"
  t('key', { count: 1 }); // -> "item"
  t('key', { count: 5 }); // -> "items"
  t('key', { count: 100 }); // -> "items"
  t('keyWithCount', { count: 0 }); // -> "0 items"
  t('keyWithCount', { count: 1 }); // -> "1 item"
  t('keyWithCount', { count: 5 }); // -> "5 items"
  t('keyWithCount', { count: 100 }); // -> "100 items"

  t('key1_interval', { postProcess: 'interval', count: 1 }); // -> "one item"
  t('key1_interval', { postProcess: 'interval', count: 4 }); // -> "a few items"
  t('key1_interval', { postProcess: 'interval', count: 100 }); // -> "a lot of items"

  // not matching into a range it will fallback to
  // the regular plural form
  t('key2_interval', { postProcess: 'interval', count: 1 }); // -> "one item"
  t('key2_interval', { postProcess: 'interval', count: 4 }); // -> "a few items"
  t('key2_interval', { postProcess: 'interval', count: 100 }); // -> "100 items"
  t('friend', { context: 'male', count: 1 }); // -> "A boyfriend"
  t('friend', { context: 'female', count: 100 }); // -> "100 girlfriends"
  t('tree', { returnObjects: true, something: 'gold' });
  // -> { res: 'added gold' }

  t('array', { returnObjects: true });
  // -> ['a', 'b', 'c']
  t('arrayJoin', { joinArrays: '+' });
  // -> "line1+line2+line3"

  const objectResult: object = t('test', { returnObjects: true });
  const detailsAndObjecbarriersLinkTexttResult: object | string | null = t('test', {
    returnObjects: true,
    returnDetails: true,
  }).res;

  // @ts-expect-error
  const notTrueObjectResult: object = t('test');

  const resolved = t('key', { returnDetails: true });
  resolved.res;
  resolved.res?.substring(2, 1);
  resolved.usedKey;
  resolved.exactUsedKey;
  resolved.usedNS;
  resolved.usedLng;
  resolved.usedParams;

  const r2 = t('keyTwo', { returnDetails: false });
  r2?.substring(0, 2); // make sure it is a string
  const r3 = t('keyThree');
  r3?.substring(0, 2); // make sure it is a string
  const r4 = t('keyTwo', { ns: 'whatever' });
  r4?.substring(0, 2); // make sure it is a string

  t('arrayJoinWithInterpolation', {
    myVar: 'interpolate',
    joinArrays: ' ',
  });
  // -> "you can interpolate"

  t('arrayOfObjects.0.name');
  // -> "tom"

  t('welcome here :)', { nsSeparator: false });
  // -> "welcome here :)"
  t('welcome ...', { keySeparator: false });
  // -> "welcome ..."
}

function nullTranslations() {
  i18next.t('nullKey').trim();
}

function usingTFunctionInsideAnotherTFunction(t: TFunction) {
  t('foobar', { defaultValue: t('inter') });

  t('foobar', { defaultValue: t('inter'), someValue: t('inter') });

  t('foobar', { something: t('inter') });
}
