using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using hive;


namespace GameNetwork
{

	public class Item
	{
		public string code;			// 아이템 코드
		public long amount;			// 아이템 수량

		public Item() {}

		public Item(JSONObject json) {
			json.GetField( ref code, "code");
			json.GetField( ref amount, "amount");
		}
	}


	public class Character
	{
		public string type;			// 사용자 타입 (캐릭터이므로 항상 'character' 값으로 전달)
		public long characterId;	// 캐릭터 아이디
		public string nickname;		// 케릭터 닉네임
		public List<Item> items;	// 캐릭터가 소유하고 있는 모든 아이템 정보

		public Character() {}

		public Character(JSONObject json)
		{
			json.GetField( ref type, "type");
			json.GetField( ref characterId, "character_id");
			json.GetField( ref nickname, "nickname");

			JSONObject jsonArrayItems = json.GetField("items");

			if (jsonArrayItems != null)
			{
				items = new List<Item>();

				if (jsonArrayItems.count > 0)
				{
					foreach (JSONObject j in jsonArrayItems.list)
					{
						items.Add(new Item(j));
					}
				}
			}
		}
	}


	public class Subscription
	{
		public string productId;	// 아이템 코드
		public int marketId;		// 구독 구매 마켓, 1:애플, 2:구글
		public long startDateMs;	// 구독 시작시간 unix timestamp
		public long expireDateMs;	// 구독 만료시간 unix timestamp
		public int groupId;			// 그룹 넘버, 같은 숫자는 동일 그룹으로 본다
		public string periodType;	// 구독 주기 타입, week, month, year
		public int period;          // 구독 주기수, periodType 이 week 이고 period 가 1이면 1주 상품
		public string nextProductId;	// 다음 주기에 갱신될 아이템 코드

        public Subscription() {}

		public Subscription(JSONObject json) {
			json.GetField( ref productId, "product_id");
			json.GetField( ref marketId, "market_id");
			json.GetField( ref startDateMs, "start_date_ms");
			json.GetField( ref expireDateMs, "expire_date_ms");
			json.GetField( ref groupId, "group_id");
			json.GetField( ref periodType, "subscription_period_type");
			json.GetField( ref period, "subscription_period");
			json.GetField( ref nextProductId, "next_product_id");
		}
	}


	public class Post
	{
		public int postId;			// 우편 아이디
		public string userMessage;	// 우편 메시지
		public string itemCode;		// 우편에 첨부된 아이템 코드
		public long itemAmount;		// 우편에 첨부된 아이템 수량
		public string date;			// 수신 날짜

		public Post() {}

		public Post(JSONObject json) {
			json.GetField( ref postId, "post_id");
			json.GetField( ref userMessage, "user_message");
			json.GetField( ref itemCode, "item_code");
			json.GetField( ref itemAmount, "item_amount");
			json.GetField( ref date, "date");
		}
	}


	public class Score
	{
		public string nickname;		// 스코어를 기록한 계정 또는 캐릭터 닉네임
		public long score;			// 정수 형태의 스코어 수치
		public string date;			// 스코어를 기록한 날짜

		public Score() {}

		public Score(JSONObject json) {
			json.GetField( ref nickname, "nickname");
			json.GetField( ref score, "score");
			json.GetField( ref date, "date");
		}
	}


	public class Response	// base
	{
		public int resultCode = -1;
		public string resultMessage = "";

		public string originalMessage = null;
		protected JSONObject jsonData = null;
		

		public Response(string responseString) {
			this.originalMessage = responseString;

			if ( String.IsNullOrEmpty(this.originalMessage) ) {
				resultCode = -9998; // TODO
				resultMessage = "response message is Null or Empty!";

			} else {
				JSONObject json = new JSONObject(responseString);

				if (json.type == JSONObject.Type.Object) {
					json.GetField( ref resultCode, "result_code");
					json.GetField( ref resultMessage, "result_message");
					jsonData = json.GetField("result_data");

				} else {
					jsonData = null;
					resultCode = -9999; // TODO
					resultMessage = "response json parse ERROR!" + "\n" + this.originalMessage;
				}

			}
		}

		public bool isSuccess() {
			return resultCode == 0;
		}

		public bool isFailure() {
			return !isSuccess();
		}
	}// end of Response class


	public class ResponseAccountLogin : Response
	{
		public string type;					// 사용자 타입 (계정이므로 항상 'account' 값으로 전달)
		public long playerId;				// PlayerID
		public string nickname;				// 계정 닉네임
		public string sessionToken;			// 인증이 필요한 요청시 필수 값으로 사용되는 세션 토큰
		public List<Item> items;			// 계정이 소유하고 있는 모든 아이템 정보
		public List<Character> characters;	// 계정이 소유하고 있는 모든 캐릭터 정보
		public List<Subscription> subscriptions;	// 계정이 구매하고 있는 모든 구독 상품 정보
		public List<Subscription> subscriptionMetaDatas;		// 판매하고 있는 상품 정보


		public ResponseAccountLogin(string response) : base(response) {
			
			if (base.isSuccess()) {

				base.jsonData.GetField(ref type, "type");
				base.jsonData.GetField(ref playerId, "player_id");
				base.jsonData.GetField(ref nickname, "nickname");
				base.jsonData.GetField(ref sessionToken, "session_token");

				JSONObject jsonArrayItems = base.jsonData.GetField("items");

				if (jsonArrayItems != null)
				{
					items = new List<Item>();

					if (jsonArrayItems.count > 0)
					{
						foreach (JSONObject j in jsonArrayItems.list)
						{
							items.Add(new Item(j));
						}
					}
				}

				JSONObject jsonArrayCharacters = base.jsonData.GetField("characters");

				if (jsonArrayCharacters != null && jsonArrayCharacters.count > 0) {
					characters = new List<Character>();

					foreach (JSONObject j in jsonArrayCharacters.list) {
						characters.Add(new Character(j));
					}
				}

				JSONObject jsonArraySubscriptions = base.jsonData.GetField("subscriptions");

				if (jsonArraySubscriptions != null && jsonArraySubscriptions.count > 0) {
					subscriptions = new List<Subscription>();

					foreach (JSONObject j in jsonArraySubscriptions.list) {
						subscriptions.Add(new Subscription(j));
					}
				}

				JSONObject jsonArraySubscriptionMetaDatas = base.jsonData.GetField("meta_subscriptions");

				if (jsonArraySubscriptionMetaDatas != null && jsonArraySubscriptionMetaDatas.count > 0) {
					subscriptionMetaDatas = new List<Subscription>();

					foreach (JSONObject j in jsonArraySubscriptionMetaDatas.list) {
						subscriptionMetaDatas.Add(new Subscription(j));
					}
				}
				
				// TODO log
			}
		}

	}	// end of ResponseAccountLogin class


	public class ResponseCharacterLogin : Response
	{
		public string type;					// 사용자 타입 (캐릭터이므로 항상 'character' 값으로 전달)
		public long characterId;			// 캐릭터 아이디
		public string nickname;				// 캐릭터 닉네임
		public List<Item> items;			// 캐릭터가 소유하고 있는 모든 아이템 정보


		public ResponseCharacterLogin(string response) : base(response) {
			
			if (base.isSuccess()) {

				base.jsonData.GetField(ref type, "type");
				base.jsonData.GetField(ref characterId, "character_id");
				base.jsonData.GetField(ref nickname, "nickname");

				JSONObject jsonArrayItems = base.jsonData.GetField("items");

				if (jsonArrayItems != null)
				{
					items = new List<Item>();

					if (jsonArrayItems.count > 0)
					{
						foreach (JSONObject j in jsonArrayItems.list)
						{
							items.Add(new Item(j));
						}
					}
				}

				// TODO log
			}
		}

	}	// end of ResponseCharacterLogin class


	public class ResponseCharacterRegister : Response
	{
		public string type;					// 사용자 타입 (캐릭터이므로 항상 'character' 값으로 전달)
		public long characterId;			// 캐릭터 아이디
		public string nickname;				// 캐릭터 닉네임
		public List<Item> items;			// 캐릭터가 소유하고 있는 모든 아이템 정보


		public ResponseCharacterRegister(string response) : base(response) {
			
			if (base.isSuccess()) {

				base.jsonData.GetField(ref type, "type");
				base.jsonData.GetField(ref characterId, "character_id");
				base.jsonData.GetField(ref nickname, "nickname");

				JSONObject jsonArrayItems = base.jsonData.GetField("items");

				if (jsonArrayItems != null)
				{
					items = new List<Item>();

					if (jsonArrayItems.count > 0)
                    {
						foreach (JSONObject j in jsonArrayItems.list)
						{
							items.Add(new Item(j));
						}
					}
				}

				// TODO log
			}
		}

	}	// end of ResponseCharacterRegister class


	public class ResponseAccountGetItems : Response
	{
		public long playerId;					//PlayerID
		public long characterId;				// 캐릭터 아이디
		public List<Item> accountItems;			// 계정이 소유하고 있는 모든 아이템 정보
		public List<Item> characterItems;		// 캐릭터가 소유하고 있는 모든 아이템 정보
		public List<Subscription> subscriptions;	// 계정이 구매하고 있는 모든 구독 상품 정보
		public List<Subscription> subscriptionMetaDatas;		// 판매하고 있는 상품 정보


		public ResponseAccountGetItems(string response) : base(response) {

			if (base.isSuccess()) {

				base.jsonData.GetField(ref characterId, "player_id");
				base.jsonData.GetField(ref characterId, "character_id");

				JSONObject jsonArrayAccountItems = base.jsonData.GetField("account_items");

				if (jsonArrayAccountItems != null)
				{ 
					accountItems = new List<Item>();

					if (jsonArrayAccountItems.count > 0)
					{
						foreach (JSONObject j in jsonArrayAccountItems.list)
						{
							accountItems.Add(new Item(j));
						}
					}
				}

				JSONObject jsonArrayCharacterItems = base.jsonData.GetField("character_items");

				if (jsonArrayCharacterItems != null)
				{
					characterItems = new List<Item>();

					if (jsonArrayCharacterItems.count > 0)
					{
						foreach (JSONObject j in jsonArrayCharacterItems.list)
						{
							characterItems.Add(new Item(j));
						}
					}				
				}

				JSONObject jsonArraySubscriptions = base.jsonData.GetField("subscriptions");

				if (jsonArraySubscriptions != null)
				{
					subscriptions = new List<Subscription>();

					if (jsonArraySubscriptions.count > 0)
					{
						foreach (JSONObject j in jsonArraySubscriptions.list)
						{
							subscriptions.Add(new Subscription(j));
						}
					}
				}

				JSONObject jsonArraySubscriptionMetaDatas = base.jsonData.GetField("meta_subscriptions");

				if (jsonArraySubscriptionMetaDatas != null)
				{
					subscriptionMetaDatas = new List<Subscription>();

					if (jsonArraySubscriptionMetaDatas.count > 0)
                    {
						foreach (JSONObject j in jsonArraySubscriptionMetaDatas.list)
						{
							subscriptionMetaDatas.Add(new Subscription(j));
						}
					}
				}

				// TODO log
			}
		}

	}	// end of ResponseAccountConsumeItem class


	public class ResponseAccountConsumeItem : Response
	{
		public List<Item> items;			// 계정이 소유하고 있는 모든 아이템 정보


		public ResponseAccountConsumeItem(string response) : base(response) {
			
			if (base.isSuccess()) {

				JSONObject jsonArrayItems = base.jsonData.GetField("items");

				if (jsonArrayItems != null)
				{
					items = new List<Item>();

					if (jsonArrayItems.count > 0)
                    {
						foreach (JSONObject j in jsonArrayItems.list)
						{
							items.Add(new Item(j));
						}
					}
				}

				// TODO log
			}
		}

	}	// end of ResponseAccountConsumeItem class


	public class ResponseAccountPurchaseItem : Response
	{
		public List<Item> items;			// 계정이 소유하고 있는 모든 아이템 정보


		public ResponseAccountPurchaseItem(string response) : base(response) {

			if (base.isSuccess()) {

				JSONObject jsonArrayItems = base.jsonData.GetField("items");

				if (jsonArrayItems != null)
				{
					items = new List<Item>();

					if (jsonArrayItems.count > 0)
                    {
						foreach (JSONObject j in jsonArrayItems.list)
						{
							items.Add(new Item(j));
						}
					}
				}

				// TODO log
			}
		}

	}	// end of ResponseAccountConsumeItem class


	public class ResponsePostboxPosts : Response
	{
		public List<Post> posts;			// 계정이 소유하고 있는 모든 아이템 정보


		public ResponsePostboxPosts(string response) : base(response) {
			
			if (base.isSuccess()) {

				JSONObject jsonArrayPosts = base.jsonData.GetField("posts");

				if (jsonArrayPosts != null)
				{
					posts = new List<Post>();

					if (jsonArrayPosts.count > 0)
                    {
						foreach (JSONObject j in jsonArrayPosts.list)
						{
							posts.Add(new Post(j));
						}
					}
				}

				// TODO log
			}
		}

	}	// end of ResponsePostboxPosts class


	public class ResponsePostboxReceive : Response
	{
		public List<Post> posts;			// 계정이 소유하고 있는 모든 아이템 정보


		public ResponsePostboxReceive(string response) : base(response) {
			
			if (base.isSuccess()) {

				JSONObject jsonArrayPosts = base.jsonData.GetField("posts");

				if (jsonArrayPosts != null)
				{
					posts = new List<Post>();

					if (jsonArrayPosts.count > 0)
                    {
						foreach (JSONObject j in jsonArrayPosts.list)
						{
							posts.Add(new Post(j));
						}
					}
				}

				// TODO log
			}
		}

	}	// end of ResponsePostboxReceive class


	public class ResponseScoreRank : Response
	{
		public string scoreType;			// 스코어 타입 값
		public List<Score> scores;			// 요청한 타입에 대한 모든 스코어 정보


		public ResponseScoreRank(string response) : base(response) {
			
			if (base.isSuccess()) {

				JSONObject jsonArrayScores = base.jsonData.GetField("scores");

				if (jsonArrayScores != null)
				{
					scores = new List<Score>();

					if (jsonArrayScores.count > 0)
                    {
						foreach (JSONObject j in jsonArrayScores.list)
						{
							scores.Add(new Score(j));
						}
					}
				}

				// TODO log
			}
		}

	}	// end of ResponseScoreRank class


	public class ResponseScoreSend : Response
	{
		public ResponseScoreSend(string response) : base(response) {}

	}	// end of ResponseScoreSend class


	public class ResponseAccountInfo : Response
	{
		public string type;					// 사용자 타입 (계정이므로 항상 'account' 값으로 전달)
		public long playerId;				// PlayerID
		public string nickname;				// 계정 닉네임
		public List<Item> items;			// 계정이 소유하고 있는 모든 아이템 정보
		public List<Character> characters;	// 계정이 소유하고 있는 모든 캐릭터 정보


		public ResponseAccountInfo(string response) : base(response) {

			if (base.isSuccess()) {

				base.jsonData.GetField(ref type, "type");
				base.jsonData.GetField(ref playerId, "player_id");
				base.jsonData.GetField(ref nickname, "nickname");

				JSONObject jsonArrayItems = base.jsonData.GetField("items");

				if (jsonArrayItems != null) {
					items = new List<Item>();

					if (jsonArrayItems.count > 0)
                    {
						foreach (JSONObject j in jsonArrayItems.list)
						{
							items.Add(new Item(j));
						}
					}
					
				}

				JSONObject jsonArrayCharacters = base.jsonData.GetField("characters");

				if (jsonArrayCharacters != null)
				{
					characters = new List<Character>();

					if (jsonArrayCharacters.count > 0)
                    {
						foreach (JSONObject j in jsonArrayCharacters.list)
						{
							characters.Add(new Character(j));
						}
					}
				}

				// TODO log
			}
		}
	}	// end of ResponseAccountInfo class


	public class ResponseBillingVerify : Response
	{
		public string marketPid;
		public long ownedPlayerId;

		public ResponseBillingVerify(string response) : base(response) {

			if (base.isSuccess ()) {

				base.jsonData.GetField (ref marketPid, "product_id");
				base.jsonData.GetField (ref ownedPlayerId, "owned_player_id");

				// TODO log
			}
		}

	}	// end of ResponseBillingVerify class


} // end of namespace game
