using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using Cute;
using UnityEngine;
using ZXing;
using ZXing.QrCode;
using ZXing.QrCode.Internal;

namespace Wizard;

public class QRCodeUtility
{
	public struct DeckDataFromQRCode
	{
		public CardBasePrm.ClanType ClanId;

		public CardBasePrm.ClanType SubClanId;

		public int[] CardIds;

		public bool IsSubClassSet;

		public Format Format;

		public MyRotationInfo MyRotationInfo { get; }

		public DeckDataFromQRCode(Format format, CardBasePrm.ClanType clanId, CardBasePrm.ClanType subClanId, int[] cardIds, MyRotationInfo myRotationInfo)
		{
			ClanId = clanId;
			CardIds = cardIds;
			SubClanId = subClanId;
			IsSubClassSet = CardBasePrm.ClanTypeIsUseable(subClanId);
			Format = format;
			MyRotationInfo = myRotationInfo;
		}
	}

	public const int SIZE_SMALL = 207;

	public const int SIZE_BIG = 508;

	public const int BIGQRCODE_TEXTURE_WIDGIT_SIZE = 400;

	private const string NORMAL_URL_TAIL = "/deck/";

	private const string CROSSOVER_URL_TAIL = "/deck_co/";

	private const string MY_ROTATION_URL_TAIL = "/deck_my/";

	public static DeckDataFromQRCode deckDataFromQRCode;

	public static Texture2D CreateQrCodeTexture(int width, int height, string content)
	{
		BarcodeWriter barcodeWriter = new BarcodeWriter
		{
			Format = BarcodeFormat.QR_CODE,
			Options = new QrCodeEncodingOptions
			{
				ErrorCorrection = ErrorCorrectionLevel.L,
				Width = width,
				Height = height
			}
		};
		Texture2D texture2D = new Texture2D(width, height, TextureFormat.ARGB32, mipChain: false);
		Color32[] pixels = barcodeWriter.Write(content);
		texture2D.SetPixels32(pixels);
		texture2D.Apply();
		return texture2D;
	}

	private static string GetAppendUrlFromDeckType(IFormatBehavior formatBehavior, Format format)
	{
		if (formatBehavior.UseSubClass)
		{
			return "/deck_co/";
		}
		if (format == Format.MyRotation)
		{
			return "/deck_my/";
		}
		return "/deck/";
	}

	public static string GenerateQRCodeText(List<int> deckList, CardBasePrm.ClanType? clanType, ClassSet classSet, IFormatBehavior formatBehavior, Format format, MyRotationInfo myRotationInfo)
	{
		bool useSubClass = formatBehavior.UseSubClass;
		StringBuilder tempStringBuilder = UIUtil.GetTempStringBuilder();
		tempStringBuilder.Append("https://").Append("shadowverse-portal.com/api/v1/game_api/".Split('/')[0]);
		tempStringBuilder.Append(GetAppendUrlFromDeckType(formatBehavior, format));
		tempStringBuilder.Append(((int)formatBehavior.DeckCodeType).ToString()).Append(".");
		string value;
		if (classSet == null)
		{
			value = ((int)clanType.Value).ToString();
		}
		else
		{
			int mainClass = (int)classSet.MainClass;
			value = mainClass.ToString();
		}
		tempStringBuilder.Append(value).Append(".");
		if (useSubClass)
		{
			int mainClass = (int)classSet.SubClass;
			tempStringBuilder.Append(mainClass.ToString()).Append(".");
		}
		if (format == Format.MyRotation)
		{
			tempStringBuilder.Append(myRotationInfo.Id).Append(".");
		}
		CardMaster instance = CardMaster.GetInstance(formatBehavior.CardMasterId);
		for (int i = 0; i < deckList.Count; i++)
		{
			int normalCardId = instance.GetCardParameterFromId(deckList[i]).NormalCardId;
			tempStringBuilder.Append(instance.GetCardParameterFromId(normalCardId).CardHashId);
			if (i != deckList.Count - 1)
			{
				tempStringBuilder.Append(".");
			}
		}
		tempStringBuilder.Append("?lang=").Append(GetLanguageCode());
		return tempStringBuilder.ToString();
	}

	public static string GetLanguageCode()
	{
		string result = "";
		switch (CustomPreference.GetTextLanguage())
		{
		case "Jpn":
			result = "ja";
			break;
		case "Ger":
			result = "de";
			break;
		case "Fre":
			result = "fr";
			break;
		case "Ita":
			result = "it";
			break;
		case "Cht":
			result = "zh-tw";
			break;
		case "Kor":
			result = "ko";
			break;
		case "Spa":
			result = "es";
			break;
		case "Chs":
		case "Eng":
			result = "en";
			break;
		}
		return result;
	}

	public static string DecodeContentText(WebCamTexture webCamTexture)
	{
		if (webCamTexture == null)
		{
			return string.Empty;
		}
		return DecodeContentText(webCamTexture.GetPixels32(), webCamTexture.width, webCamTexture.height, isFromCamera: true);
	}

	public static string DecodeContentText(Color32[] pixels, int width, int height, bool isFromCamera)
	{
		BarcodeReader barcodeReader = new BarcodeReader
		{
			AutoRotate = !isFromCamera
		};
		Result result;
		try
		{
			result = barcodeReader.Decode(pixels, width, height);
		}
		catch (Exception ex)
		{
			LocalLog.AccumulateTraceLog("#699501 :" + ex);
			result = null;
		}
		if (result == null)
		{
			return string.Empty;
		}
		return result.Text;
	}

	public static bool SetDeckFromQRCodeText(string qrCodeText, CardMaster.CardMasterId cardMasterId)
	{
		bool result = false;
		string text = "https://" + "shadowverse-portal.com/api/v1/game_api/".Split('/')[0] + "/deck/";
		string text2 = "https://" + "shadowverse-portal.com/api/v1/game_api/".Split('/')[0] + "/deck_co/";
		string text3 = "https://" + "shadowverse-portal.com/api/v1/game_api/".Split('/')[0] + "/deck_my/";
		bool flag = qrCodeText.StartsWith(text);
		bool flag2 = qrCodeText.StartsWith(text2);
		bool flag3 = qrCodeText.StartsWith(text3);
		if (!flag && !flag2 && !flag3)
		{
			return result;
		}
		if (!Regex.IsMatch(qrCodeText, "\\?lang=(\\w+$|zh-tw)"))
		{
			return result;
		}
		if (flag)
		{
			qrCodeText = Regex.Replace(qrCodeText, text, "");
		}
		else if (flag2)
		{
			qrCodeText = Regex.Replace(qrCodeText, text2, "");
		}
		else if (flag3)
		{
			qrCodeText = Regex.Replace(qrCodeText, text3, "");
		}
		qrCodeText = Regex.Replace(qrCodeText, "\\?lang=(\\w+$|zh-tw)", "");
		string[] array = qrCodeText.Split('.');
		CardBasePrm.ClanType clanType = CardBasePrm.ClanType.NONE;
		CardBasePrm.ClanType subClanId = CardBasePrm.ClanType.NONE;
		MyRotationInfo myRotationInfo = null;
		Format format = Format.Max;
		try
		{
			format = GetFormatFromDeckCodeType((GenerateDeckCodeTask.SubmitDeckType)int.Parse(array[0]));
			clanType = (CardBasePrm.ClanType)int.Parse(array[1]);
			if (flag2)
			{
				subClanId = (CardBasePrm.ClanType)int.Parse(array[2]);
			}
			if (flag3)
			{
				myRotationInfo = Data.MyRotationAllInfo.Get(array[2]);
			}
			if (clanType < CardBasePrm.ClanType.MIN || clanType > CardBasePrm.ClanType.MAX)
			{
				return result;
			}
		}
		catch (Exception ex)
		{
			if (array.Length >= 3)
			{
				Debug.LogError($"フォーマット: {array[0].ToString()}、クラス: {array[1].ToString()}、サブクラス: {array[2].ToString()}のいずれかの情報取得に失敗。{ex.ToString()}");
			}
			else
			{
				Debug.LogError($"cardHashIdListの長さが{array.Length.ToString()}です。{ex.ToString()}");
			}
			return result;
		}
		List<int> list = new List<int>();
		int num = 2;
		if (flag2 || flag3)
		{
			num = 3;
		}
		for (int i = num; i < array.Length; i++)
		{
			try
			{
				int cardId = CardMaster.GetInstance(cardMasterId).GetCardParamFromCardHashId(array[i]).CardId;
				if (!CardMaster.GetInstance(cardMasterId).CardExists(cardId))
				{
					return result;
				}
				list.Add(cardId);
			}
			catch (Exception ex2)
			{
				Debug.LogError($"カードリストの{i.ToString()}番目要素の取得に失敗。{ex2.ToString()}");
				return result;
			}
		}
		deckDataFromQRCode = new DeckDataFromQRCode(format, clanType, subClanId, list.ToArray(), myRotationInfo);
		return true;
	}

	public static Format GetFormatFromDeckCodeType(GenerateDeckCodeTask.SubmitDeckType type)
	{
		return type switch
		{
			GenerateDeckCodeTask.SubmitDeckType.NORMAL => Format.Unlimited, 
			GenerateDeckCodeTask.SubmitDeckType.Crossover => Format.Crossover, 
			_ => Format.Max, 
		};
	}

	public static bool IsShowQRCode(UICardList deckViewer, IFormatBehavior formatBehavior, Format format)
	{
		bool flag = deckViewer.getCardNum() == 40;
		if (formatBehavior.UseSubClass)
		{
			flag &= deckViewer.CanShowQRCodeUseSubclass();
		}
		if (format == Format.MyRotation && !deckViewer.IsDeckNull())
		{
			flag &= deckViewer.IsAllCardCorrectMyRotation();
		}
		if (format == Format.Avatar)
		{
			flag = false;
		}
		return flag;
	}
}
