// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
*******************************************************************************
* Copyright (C) 2008-2013, International Business Machines Corporation and
* others. All Rights Reserved.
*******************************************************************************
*
*
* File GENDER.CPP
*
* Modification History:*
*   Date        Name        Description
*
********************************************************************************
*/

#include "unicode/utypes.h"

#if !UCONFIG_NO_FORMATTING

#include "unicode/gender.h"
#include "unicode/ugender.h"
#include "unicode/ures.h"

#include "cmemory.h"
#include "cstring.h"
#include "mutex.h"
#include "uassert.h"
#include "ucln_in.h"
#include "umutex.h"
#include "uhash.h"

static UHashtable* gGenderInfoCache = NULL;

static const char* gNeutralStr = "neutral";
static const char* gMailTaintsStr = "maleTaints";
static const char* gMixedNeutralStr = "mixedNeutral";
static icu::GenderInfo* gObjs = NULL;
static icu::UInitOnce gGenderInitOnce {};

enum GenderStyle {
  NEUTRAL,
  MIXED_NEUTRAL,
  MALE_TAINTS,
  GENDER_STYLE_LENGTH
};

U_CDECL_BEGIN

static UBool U_CALLCONV gender_cleanup(void) {
  if (gGenderInfoCache != NULL) {
    uhash_close(gGenderInfoCache);
    gGenderInfoCache = NULL;
    delete [] gObjs;
  }
  gGenderInitOnce.reset();
  return TRUE;
}

U_CDECL_END

U_NAMESPACE_BEGIN

void U_CALLCONV GenderInfo_initCache(UErrorCode &status) {
  ucln_i18n_registerCleanup(UCLN_I18N_GENDERINFO, gender_cleanup);
  U_ASSERT(gGenderInfoCache == NULL);
  if (U_FAILURE(status)) {
      return;
  }
  gObjs = new GenderInfo[GENDER_STYLE_LENGTH];
  if (gObjs == NULL) {
    status = U_MEMORY_ALLOCATION_ERROR;
    return;
  }
  for (int i = 0; i < GENDER_STYLE_LENGTH; i++) {
    gObjs[i]._style = i;
  }
  gGenderInfoCache = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &status);
  if (U_FAILURE(status)) {
    delete [] gObjs;
    return;
  }
  uhash_setKeyDeleter(gGenderInfoCache, uprv_free);
}


GenderInfo::GenderInfo() {
}

GenderInfo::~GenderInfo() {
}

const GenderInfo* GenderInfo::getInstance(const Locale& locale, UErrorCode& status) {
  // Make sure our cache exists.
  umtx_initOnce(gGenderInitOnce, &GenderInfo_initCache, status);
  if (U_FAILURE(status)) {
    return NULL;
  }

  static UMutex gGenderMetaLock;
  const GenderInfo* result = NULL;
  const char* key = locale.getName();
  {
    Mutex lock(&gGenderMetaLock);
    result = (const GenderInfo*) uhash_get(gGenderInfoCache, key);
  }
  if (result) {
    return result;
  }

  // On cache miss, try to create GenderInfo from CLDR data
  result = loadInstance(locale, status);
  if (U_FAILURE(status)) {
    return NULL;
  }

  // Try to put our GenderInfo object in cache. If there is a race condition,
  // favor the GenderInfo object that is already in the cache.
  {
    Mutex lock(&gGenderMetaLock);
    GenderInfo* temp = (GenderInfo*) uhash_get(gGenderInfoCache, key);
    if (temp) {
      result = temp;
    } else {
      uhash_put(gGenderInfoCache, uprv_strdup(key), (void*) result, &status);
      if (U_FAILURE(status)) {
        return NULL;
      }
    }
  }
  return result;
}

const GenderInfo* GenderInfo::loadInstance(const Locale& locale, UErrorCode& status) {
  LocalUResourceBundlePointer rb(
      ures_openDirect(NULL, "genderList", &status));
  if (U_FAILURE(status)) {
    return NULL;
  }
  LocalUResourceBundlePointer locRes(ures_getByKey(rb.getAlias(), "genderList", NULL, &status));
  if (U_FAILURE(status)) {
    return NULL;
  }
  int32_t resLen = 0;
  const char* curLocaleName = locale.getName();
  UErrorCode key_status = U_ZERO_ERROR;
  const UChar* s = ures_getStringByKey(locRes.getAlias(), curLocaleName, &resLen, &key_status);
  if (s == NULL) {
    key_status = U_ZERO_ERROR;
    char parentLocaleName[ULOC_FULLNAME_CAPACITY];
    uprv_strcpy(parentLocaleName, curLocaleName);
    while (s == NULL && uloc_getParent(parentLocaleName, parentLocaleName, ULOC_FULLNAME_CAPACITY, &key_status) > 0) {
      key_status = U_ZERO_ERROR;
      resLen = 0;
      s = ures_getStringByKey(locRes.getAlias(), parentLocaleName, &resLen, &key_status);
      key_status = U_ZERO_ERROR;
    }
  }
  if (s == NULL) {
    return &gObjs[NEUTRAL];
  }
  char type_str[256] = "";
  u_UCharsToChars(s, type_str, resLen + 1);
  if (uprv_strcmp(type_str, gNeutralStr) == 0) {
    return &gObjs[NEUTRAL];
  }
  if (uprv_strcmp(type_str, gMixedNeutralStr) == 0) {
    return &gObjs[MIXED_NEUTRAL]; 
  }
  if (uprv_strcmp(type_str, gMailTaintsStr) == 0) {
    return &gObjs[MALE_TAINTS];
  }
  return &gObjs[NEUTRAL];
}

UGender GenderInfo::getListGender(const UGender* genders, int32_t length, UErrorCode& status) const {
  if (U_FAILURE(status)) {
    return UGENDER_OTHER;
  }
  if (length == 0) {
    return UGENDER_OTHER;
  }
  if (length == 1) {
    return genders[0];
  }
  UBool has_female = FALSE;
  UBool has_male = FALSE;
  switch (_style) {
    case NEUTRAL:
      return UGENDER_OTHER;
    case MIXED_NEUTRAL:
      for (int32_t i = 0; i < length; ++i) {
        switch (genders[i]) {
          case UGENDER_OTHER:
            return UGENDER_OTHER;
            break;
          case UGENDER_FEMALE:
            if (has_male) {
              return UGENDER_OTHER;
            }
            has_female = TRUE;
            break;
          case UGENDER_MALE:
            if (has_female) {
              return UGENDER_OTHER;
            }
            has_male = TRUE;
            break;
          default:
            break;
        }
      }
      return has_male ? UGENDER_MALE : UGENDER_FEMALE;
      break;
    case MALE_TAINTS:
      for (int32_t i = 0; i < length; ++i) {
        if (genders[i] != UGENDER_FEMALE) {
          return UGENDER_MALE;
        }
      }
      return UGENDER_FEMALE;
      break;
    default:
      return UGENDER_OTHER;
      break;
  }
}

const GenderInfo* GenderInfo::getNeutralInstance() {
  return &gObjs[NEUTRAL];
}

const GenderInfo* GenderInfo::getMixedNeutralInstance() {
  return &gObjs[MIXED_NEUTRAL];
}

const GenderInfo* GenderInfo::getMaleTaintsInstance() {
  return &gObjs[MALE_TAINTS];
}

U_NAMESPACE_END

U_CAPI const UGenderInfo* U_EXPORT2
ugender_getInstance(const char* locale, UErrorCode* status) {
  return (const UGenderInfo*) icu::GenderInfo::getInstance(locale, *status);
}

U_CAPI UGender U_EXPORT2
ugender_getListGender(const UGenderInfo* genderInfo, const UGender* genders, int32_t size, UErrorCode* status) {
  return ((const icu::GenderInfo *)genderInfo)->getListGender(genders, size, *status);
}

#endif /* #if !UCONFIG_NO_FORMATTING */
