using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using GamestatsBase;
using PkmnFoundations.Data;
using PkmnFoundations.Structures;
using PkmnFoundations.Wfc;

namespace PkmnFoundations.GTS
{
    /// <summary>
    /// Gamestats handler for Wi-Fi Plaza
    /// </summary>
    public class pokemondpds_web : GamestatsHandler
    {
        public pokemondpds_web()
            : base("uLMOGEiiJogofchScpXb000244fd00006015100000005b440e7epokemondpds",
            GamestatsRequestVersions.Version3, GamestatsResponseVersions.Version2, true, true)
        {

        }

        public override void ProcessGamestatsRequest(byte[] request, MemoryStream response, string url, int pid, HttpContext context, GamestatsSession session)
        {
            switch (url)
            {
                default:
                    SessionManager.Remove(session);

                    // unrecognized page url
                    ShowError(context, 404);
                    return;

                case "/pokemondpds/web/enc/lobby/checkProfile.asp":
                {
                    if (request.Length != 168)
                    {
                        ShowError(context, 400);
                        return;
                    }

                    byte[] requestData = new byte[164];

                    Array.Copy(request, 4, requestData, 0, 164);

                    TrainerProfilePlaza requestProfile = new TrainerProfilePlaza(pid, requestData);
                    Database.Instance.PlazaSetProfile(requestProfile);

                    TrainerProfilePlaza responseProfile = Database.Instance.PlazaGetProfile(requestProfile.PID);
                    response.Write(responseProfile.Data, 12, 152); // skip first 12 bytes of profile data on response

                } break;

                case "/pokemondpds/web/enc/lobby/getSchedule.asp":
                {
                    // This is a replayed response from a game I had with Pipian.
                    // It appears to be 49 ints.
                    // todo(mythra): A real implementation
                    // - we can generate events manually now, but we have a few
                    // missing fields, so more research will need to be done before
                    // that implementation.

                    // note(mythra): this response is usually overwritten by the
                    // peerchat server (through GETCHANKEY `b_lib_c_lobby`).
                    // this is only taken if that channel key returns an
                    // "empty" response.
                    PlazaSchedule ps = new PlazaSchedule();
                    ps.Duration = 1200;
                    ps.Unknown1 = -1485781858;
                    ps.FootprintOptions = PlazaFootprintOptions.Normal;
                    ps.RoomType = PlazaRoomTypes.Grass;
                    ps.Season = PlazaSeasons.None;
                    ps.Schedule = new[]
                    {
                        // todo: Have different, randomized schedules but in a way that makes sense
                        new PlazaScheduleEntry(0, (PlazaEventTypes)1),
                        new PlazaScheduleEntry(0, (PlazaEventTypes)7),
                        new PlazaScheduleEntry(0, (PlazaEventTypes)11),
                        new PlazaScheduleEntry(780, (PlazaEventTypes)8),
                        new PlazaScheduleEntry(840, (PlazaEventTypes)2),
                        new PlazaScheduleEntry(840, (PlazaEventTypes)9),
                        new PlazaScheduleEntry(900, (PlazaEventTypes)3),
                        new PlazaScheduleEntry(900, (PlazaEventTypes)10),
                        new PlazaScheduleEntry(900, (PlazaEventTypes)12),
                        new PlazaScheduleEntry(960, (PlazaEventTypes)4),
                        new PlazaScheduleEntry(960, (PlazaEventTypes)9),
                        new PlazaScheduleEntry(960, (PlazaEventTypes)13),
                        new PlazaScheduleEntry(960, (PlazaEventTypes)15),
                        new PlazaScheduleEntry(1020, (PlazaEventTypes)5),
                        new PlazaScheduleEntry(1020, (PlazaEventTypes)14),
                        new PlazaScheduleEntry(1020, (PlazaEventTypes)16),
                        new PlazaScheduleEntry(1075, (PlazaEventTypes)18),
                        new PlazaScheduleEntry(1080, (PlazaEventTypes)6),
                        new PlazaScheduleEntry(1080, (PlazaEventTypes)13),
                        new PlazaScheduleEntry(1080, (PlazaEventTypes)17),
                        new PlazaScheduleEntry(1140, (PlazaEventTypes)11),
                        new PlazaScheduleEntry(1200, (PlazaEventTypes)19),
                    };

                    Random rand = new Random();
                    int roomChoice = rand.Next(13);

                    if (roomChoice < 1)
                    {
                        ps.RoomType = PlazaRoomTypes.Mew;
                        ps.FootprintOptions = PlazaFootprintOptions.Arceus;
                    }
                    else
                    {
                        ps.RoomType = (PlazaRoomTypes)((roomChoice - 1) / 3);
                        // todo: Seasons. Based on the irl season? Maybe use GenV's season? That would be a nice callout
                    }

                    response.Write(new byte[]
                    {
                        0x00, 0x00, 0x00, 0x00
                    }, 0, 4);
                    response.Write(ps.Save(), 0, ps.Size);

                } break;

                case "/pokemondpds/web/enc/lobby/getVIP.asp":
                {
                    // todo: keep VIPs in database
                    response.Write(new byte[] { 0x00, 0x00, 0x00, 0x00 }, 0, 4);
                    // VIPs.
                    foreach (var id in VIPIds)
                    {
                        response.Write(BitConverter.GetBytes(id), 0, 4);
                        response.Write(new byte[] { 0x00, 0x00, 0x00, 0x00 }, 0, 4);
                    }
                }
                break;

                case "/pokemondpds/web/enc/lobby/getQuestionnaire.asp":
                {
                    // This is a replayed response that asks the question,
                    // "Which move would you most like to use?" Cut/Surf/Strength
                    // It also includes results for "last week"'s survey:
                    // "Do you know anyone that looks like a Gym Leader?" Yes/No/Yes, a little
                    // Apparently it's possible not just to use built-in survey
                    // questions but to also pose unique new ones?
                    // todo: Turn this into a PlazaQuestionnaire object.
                    /*
                    response.Write(new byte[]{

                    0x00, 0x00, 0x00, 0x00, 

                    0x2a, 0x01, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01,
                    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x29, 0x01, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01,
                    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x7e, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00,
                    0x33, 0x00, 0x00, 0x00, 0x64, 0x01, 0x00, 0x00,
                    0x11, 0x01, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00
                    }, 0, 732);
                    */
                    response.Write(new byte[] { 0x0, 0x0, 0x0, 0x0 }, 0, 4);
                    response.Write(staticQuestionnaire, 0, staticQuestionnaire.Length);

                } break;

                case "/pokemondpds/web/enc/lobby/submitQuestionnaire.asp":
                {
                    // One day we could parse as 'SubmittedQuestionnaire', and save in a DB somewhere.
                    // that'd be cool!
                    //
                    // literally 'thx' in ascii... lol
                    response.Write(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x74, 0x68, 0x78, 0x00 }, 0, 8);

                } break;
            }
        }

        /// <summary>
        /// The list of "VIPs".
        ///
        /// Being a VIP in a lobby just gives you a golden trainer card, and upgrades your 'Touch Toy' to the highest
        /// level right away. So far we've just been giving this to the developers who signed up for it.
        /// </summary>
        private static int[] VIPIds = new int[] { 600403373, 601315647, 601988829 };

        /// <summary>
        /// A static questionnaire, who's id is not above 1k so it doesn't load the custom question text.
        ///
        /// The last weeks results is still taken.
        /// And the footer of unknown data is copied from static responses.
        /// </summary>
        private static byte[] staticQuestionnaire = new PlazaQuestionnaire(
        new PlazaQuestion(730, "Not used", new string[] { "N/A", "N/A", "N/A" }, new byte[12], false),
        new PlazaQuestion(729, "Not used", new string[] { "N/A", "N/A", "N/A" }, new byte[12], false),
        new int[] { 69, 420, 100 },
        new byte[] { 0x64, 0x01, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00 }).Save();
    }
}
