using System.Web.Mvc;
using System.Web.Routing;
using JetBrains.Annotations;
using Microsoft.Practices.Unity;
using Portoa.Logging;
using Portoa.Search;
using Portoa.Web;
using Portoa.Web.Models;
using Portoa.Web.Security;
using Portoa.Web.SmartCasing;
using Portoa.Web.Unity;
using UnityGenerics;
using VideoGameQuotes.Api;
using VideoGameQuotes.Api.Persistence;
using VideoGameQuotes.Web.Controllers;
using VideoGameQuotes.Web.Models;
using VideoGameQuotes.Web.Security;
using VideoGameQuotes.Web.Services;

namespace VideoGameQuotes.Web {
	public class MvcApplication : MvcApplicationBase<User> {
		protected override void ConfigureModelBinders(ModelBinderDictionary binders) {
			binders
				.Add<Region, FlagEnumModelBinder<Region>>()
				.Add<BrowseModel, BrowseModelBinder>()
				.Add<ApiModel, ApiModelBinder>();
		}

		protected override void ConfigureUnity() {
			Container
				.RegisterType<VerifyUserAttribute>(new InjectionProperty<VerifyUserAttribute>(attr => attr.UserProvider))
				.RegisterAndIntercept<ICurrentUserProvider<User>, SessionBasedUserProvider>()
				.RegisterAndIntercept<IUserService, UserService>()
				.RegisterAndIntercept<IAdministrationService, AdministrationService>()
				.RegisterAndIntercept<IQuoteService, QuoteService>()
				.RegisterAndIntercept<ISystemService, SystemService>()
				.RegisterAndIntercept<ICategoryService, CategoryService>()
				.RegisterAndIntercept<IPublisherService, PublisherService>()
				.RegisterAndIntercept<IGameService, GameService>()
				.RegisterAndIntercept<IApiService, ApiService>()
				.RegisterAndIntercept<IAuthenticationService, FormsAuthenticationService>()
				.RegisterAndIntercept<IUserRepository, UserRepository>();
		}

		protected override void AfterStartUp() {
			ViewEngines.Engines.Add(new SmartCaseViewEngine(Container.Resolve<ILogger>()));
			Container.Resolve<ISearchIndexBuilder<Quote, int>>().BuildIndex();
		}

		protected override void RegisterRoutes(RouteCollection routes) {
			routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
			routes.IgnoreRoute("media/{*anything}");

			routes.MapRoute("favicon", "favicon.ico", new { controller = "Home", action = "Favicon" });

			//bullshit route so that RenderAction works
			routes.MapSmartRoute("mainmenu", "home/mainmenu", new { controller = "Home", action = "MainMenu" });
			routes.MapSmartRoute("quote-of-the-day", "quote/quoteoftheday", new { controller = "Quote", action = "QuoteOfTheDay" });
			
			routes.MapSmartRoute("crud-default", "{controller}/{action}", null, new { controller = "system|publisher|game|category", action = "create|edit|delete" });
			routes.MapSmartRoute("admin-default", "admin", new { controller = "Admin", action = "Index" });
			routes.MapSmartRoute("admin", "admin/{action}", new { controller = "Admin", action = "Index" }, new { action = "users|create|flags|password" });
			routes.MapSmartRoute("user-edit", "user/edit/{usernameOrIp}", new { controller = "User", action = "Edit", usernameOrIp = @"\w+" });
			
			routes.MapSmartRoute("api-no-criteria", "api/{action}/{id}", new { controller = "Api" }, new { action = "game|system|category|publisher|quote", id = @"\d+|all" });
			routes.MapSmartRoute("api", "api/{action}/{id}/{*criteria}", new { controller = "Api" }, new { action = "game|system|category|publisher|quote", id = @"\d+|all" });
			
			routes.MapSmartRoute("home", "{action}", new { controller = "Home", action = "Index" }, new { action = "about|contact|login|logout" });

			routes.MapSmartRoute("paged-default", "{action}", new { controller = "Quote", page = 1 }, new { action = "best|recent" });
			routes.MapSmartRoute("paged", "{action}/{page}", new { controller = "Quote", page = 1 }, new { action = "best|recent", page = @"\d+" });

			routes.MapSmartRoute("browse", "browse/{*qualifiers}", new { controller = "Quote", action = "Browse" });
			routes.MapSmartRoute("search", "search/{*searchQuery}", new { controller = "Quote", action = "Search" });
			routes.MapSmartRoute("quote", "{action}", new { controller = "Quote" }, new { action = "submit|random|vote|flag|browse" });

			//these routes don't work with constraints in mono...?
			routes.MapSmartRoute("quote-edit", "quote/edit/{id}", new { controller = "Quote", action = "Edit" });
			routes.MapSmartRoute("quote-delete", "quote/delete", new { controller = "Quote", action = "Delete" });
			routes.MapSmartRoute("quote-dismiss-flag", "quote/dismiss-flag", new { controller = "Quote", action = "DismissFlag" });
			routes.MapSmartRoute("single-quote", "quote/{id}/{*text}", new { controller = "Quote", action = "Quote" });

			//routes.MapSmartRoute("dismiss-flag", "dismiss-flag", new { controller = "Quote", action = "FooBar" });
			routes.MapSmartRoute("default", "", new { controller = "Home", action = "Index" });
		}
	}
}