/*
 * Copyright (c) 2013-2025 Hutool Team and hutool.cn
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cn.hutool.v7.extra.pinyin.engine.pinyin4j;

import cn.hutool.v7.core.array.ArrayUtil;
import cn.hutool.v7.core.lang.Assert;
import cn.hutool.v7.extra.pinyin.engine.PinyinEngine;
import cn.hutool.v7.extra.pinyin.PinyinException;
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;

/**
 * 封装了Pinyin4j的引擎。
 *
 * <p>
 * pinyin4j(<a href="http://sourceforge.net/projects/pinyin4j">http://sourceforge.net/projects/pinyin4j</a>)封装。
 * </p>
 *
 * <p>
 * 引入：
 * <pre>
 * &lt;dependency&gt;
 *     &lt;groupId&gt;com.belerweb&lt;/groupId&gt;
 *     &lt;artifactId&gt;pinyin4j&lt;/artifactId&gt;
 *     &lt;version&gt;2.5.1&lt;/version&gt;
 * &lt;/dependency&gt;
 * </pre>
 *
 * @author Looly
 */
public class Pinyin4jEngine implements PinyinEngine {

	private static final HanyuPinyinOutputFormat WITH_TONE_MARK;
	private static final HanyuPinyinOutputFormat WITHOUT_TONE;
	static {
		WITH_TONE_MARK = new HanyuPinyinOutputFormat();
		// 小写
		WITH_TONE_MARK.setCaseType(HanyuPinyinCaseType.LOWERCASE);
		// 'ü' 使用 "v" 代替
		WITH_TONE_MARK.setVCharType(HanyuPinyinVCharType.WITH_V);
		WITH_TONE_MARK.setToneType(HanyuPinyinToneType.WITH_TONE_MARK);

		WITHOUT_TONE = new HanyuPinyinOutputFormat();
		// 小写
		WITHOUT_TONE.setCaseType(HanyuPinyinCaseType.LOWERCASE);
		// 'ü' 使用 "v" 代替
		WITHOUT_TONE.setVCharType(HanyuPinyinVCharType.WITH_V);
		WITHOUT_TONE.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
	}

	/**
	 * 构造
	 */
	public Pinyin4jEngine() {
		// SPI方式加载时检查库是否引入
		Assert.notNull(PinyinHelper.class);
	}

	@Override
	public String getPinyin(final char c, final boolean tone) {
		String result;
		try {
			final String[] results = PinyinHelper.toHanyuPinyinStringArray(c, tone ? WITH_TONE_MARK : WITHOUT_TONE);
			result = ArrayUtil.isEmpty(results) ? String.valueOf(c) : results[0];
		} catch (final BadHanyuPinyinOutputFormatCombination e) {
			result = String.valueOf(c);
		}
		return result;
	}

	@Override
	public String getPinyin(final String str, final String separator, final boolean tone) {
		final StringBuilder result = new StringBuilder();
		boolean isFirst = true;
		final int strLen = str.length();
		try {
			for(int i = 0; i < strLen; i++){
				if(isFirst){
					isFirst = false;
				} else{
					result.append(separator);
				}
				final String[] pinyinStringArray = PinyinHelper.toHanyuPinyinStringArray(str.charAt(i), tone ? WITH_TONE_MARK : WITHOUT_TONE);
				if(ArrayUtil.isEmpty(pinyinStringArray)){
					result.append(str.charAt(i));
				} else{
					result.append(pinyinStringArray[0]);
				}
			}
		} catch (final BadHanyuPinyinOutputFormatCombination e) {
			throw new PinyinException(e);
		}

		return result.toString();
	}
}
