// Copyright (C) 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/********************************************************************
 * COPYRIGHT:
 * Copyright (c) 1997-2014, International Business Machines Corporation and
 * others. All Rights Reserved.
 ********************************************************************/
/* Modification History:
*/

#include "unicode/utypes.h"

#if !UCONFIG_NO_FORMATTING

#include <stdlib.h>
#include "unicode/gender.h"
#include "unicode/unum.h"
#include "intltest.h"
#include "cmemory.h"

static const UGender kSingleFemale[] = {UGENDER_FEMALE};
static const UGender kSingleMale[] = {UGENDER_MALE};
static const UGender kSingleOther[] = {UGENDER_OTHER};

static const UGender kAllFemale[] = {UGENDER_FEMALE, UGENDER_FEMALE};
static const UGender kAllMale[] = {UGENDER_MALE, UGENDER_MALE};
static const UGender kAllOther[] = {UGENDER_OTHER, UGENDER_OTHER};

static const UGender kFemaleMale[] = {UGENDER_FEMALE, UGENDER_MALE};
static const UGender kFemaleOther[] = {UGENDER_FEMALE, UGENDER_OTHER};
static const UGender kMaleOther[] = {UGENDER_MALE, UGENDER_OTHER};


class GenderInfoTest : public IntlTest {
public:
    GenderInfoTest() {
    }

    void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par=0);
private:
    void TestGetListGender();
    void TestFallback();
    void check(UGender expected_neutral, UGender expected_mixed, UGender expected_taints, const UGender* genderList, int32_t listLength);
    void checkLocale(const Locale& locale, UGender expected, const UGender* genderList, int32_t listLength);
};

void GenderInfoTest::runIndexedTest(int32_t index, UBool exec, const char *&name, char * /* par */) {
  if (exec) {
    logln("TestSuite GenderInfoTest: ");
  }
  TESTCASE_AUTO_BEGIN;
  TESTCASE_AUTO(TestGetListGender);
  TESTCASE_AUTO(TestFallback);
  TESTCASE_AUTO_END;
}

void GenderInfoTest::TestGetListGender() {
    check(UGENDER_OTHER, UGENDER_OTHER, UGENDER_OTHER, NULL, 0);
    check(UGENDER_FEMALE, UGENDER_FEMALE, UGENDER_FEMALE, kSingleFemale, UPRV_LENGTHOF(kSingleFemale));
    check(UGENDER_MALE, UGENDER_MALE, UGENDER_MALE, kSingleMale, UPRV_LENGTHOF(kSingleMale));
    check(UGENDER_OTHER, UGENDER_OTHER, UGENDER_OTHER, kSingleOther, UPRV_LENGTHOF(kSingleOther));

    check(UGENDER_OTHER, UGENDER_FEMALE, UGENDER_FEMALE, kAllFemale, UPRV_LENGTHOF(kAllFemale));
    check(UGENDER_OTHER, UGENDER_MALE, UGENDER_MALE, kAllMale, UPRV_LENGTHOF(kAllMale));
    check(UGENDER_OTHER, UGENDER_OTHER, UGENDER_MALE, kAllOther, UPRV_LENGTHOF(kAllOther));

    check(UGENDER_OTHER, UGENDER_OTHER, UGENDER_MALE, kFemaleMale, UPRV_LENGTHOF(kFemaleMale));
    check(UGENDER_OTHER, UGENDER_OTHER, UGENDER_MALE, kFemaleOther, UPRV_LENGTHOF(kFemaleOther));
    check(UGENDER_OTHER, UGENDER_OTHER, UGENDER_MALE, kMaleOther, UPRV_LENGTHOF(kMaleOther));
}

void GenderInfoTest::TestFallback() {
  UErrorCode status = U_ZERO_ERROR;
  const GenderInfo* actual = GenderInfo::getInstance("xx", status);
  if (U_FAILURE(status)) {
    errcheckln(status, "Fail to create GenderInfo - %s", u_errorName(status));
    return;
  }
  const GenderInfo* expected = GenderInfo::getNeutralInstance();
  if (expected != actual) {
    errln("For Neutral, expected %d got %d", expected, actual);
  }
  actual = GenderInfo::getInstance("fr_CA", status);
  if (U_FAILURE(status)) {
    errcheckln(status, "Fail to create GenderInfo - %s", u_errorName(status));
    return;
  }
  expected = GenderInfo::getMaleTaintsInstance();
  if (expected != actual) {
    errln("For Male Taints, Expected %d got %d", expected, actual);
  }
}

void GenderInfoTest::check(
    UGender expected_neutral, UGender expected_mixed, UGender expected_taints, const UGender* genderList, int32_t listLength) {
  checkLocale(Locale::getUS(), expected_neutral, genderList, listLength);
  checkLocale("is", expected_mixed, genderList, listLength);
  checkLocale(Locale::getFrench(), expected_taints, genderList, listLength);
}

void GenderInfoTest::checkLocale(
    const Locale& locale, UGender expected, const UGender* genderList, int32_t listLength) {
  UErrorCode status = U_ZERO_ERROR;
  const GenderInfo* gi = GenderInfo::getInstance(locale, status);
  if (U_FAILURE(status)) {
    errcheckln(status, "Fail to create GenderInfo - %s", u_errorName(status));
    return;
  }
  UGender actual = gi->getListGender(genderList, listLength, status);
  if (U_FAILURE(status)) {
    errcheckln(status, "Fail to get gender of list - %s", u_errorName(status));
    return;
  }
  if (actual != expected) {
    errln("For locale: %s expected: %d got %d", locale.getName(), expected, actual);
  }
}

extern IntlTest *createGenderInfoTest() {
  return new GenderInfoTest();
}

#endif /* #if !UCONFIG_NO_FORMATTING */
