using System;
using System.Collections.Generic;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using WebApplication1.Models;

namespace WebApplication1.Controllers {
  public class ExemplePaginationController : Controller {
    private NorthwindEntities DC = new NorthwindEntities();
    private const int TaillePage = 3;

    public ActionResult Index( string tri, string filtre, int page = 0, bool forcerLaRequeteEnBase = false ) {
      string clé = "Produits/" + filtre;
      var produitsEnCache = forcerLaRequeteEnBase ? null : (IList<ProductPourListeViewModel>)HttpContext.Cache[clé];
      filtre = (filtre ?? string.Empty).Trim();
      if( produitsEnCache == null ) {
        ViewBag.Message += " Pas en cache !";
        var rqEnBase = DC.Products.AsQueryable(); // Comme ça j'ai un IQueryable<Product>, pas un DbSet<Product>
        if( !string.IsNullOrWhiteSpace( filtre ) ) {
          rqEnBase = rqEnBase.Where( p => p.ProductName.Contains( filtre ) );
        }
        produitsEnCache = rqEnBase.Select( p => new ProductPourListeViewModel() { ProductID = p.ProductID, CategoryName = p.Category.CategoryName, ProductName = p.ProductName, UnitPrice = p.UnitPrice } ).ToList();
        HttpContext.Cache[clé] = produitsEnCache;
      }
      else {
        ViewBag.Message += " En cache !";
      }
      IEnumerable<ProductPourListeViewModel> produitsTrieesEtPaginés;
      switch( tri ) {
        case "nom_desc":
          produitsTrieesEtPaginés = produitsEnCache.OrderByDescending( p => p.ProductName );
          break;
        case "prix_asc":
          produitsTrieesEtPaginés = produitsEnCache.OrderBy( p => p.UnitPrice );
          break;
        case "prix_desc":
          produitsTrieesEtPaginés = produitsEnCache.OrderByDescending( p => p.UnitPrice );
          break;
        default:
          produitsTrieesEtPaginés = produitsEnCache.OrderBy( p => p.ProductName );
          tri = "nom_asc";
          break;
      }
      produitsTrieesEtPaginés = produitsTrieesEtPaginés.Skip( page * TaillePage ).Take( TaillePage );
      ViewBag.Filtre = filtre;
      ViewBag.Tri = tri;
      ViewBag.Page = page;
      ViewBag.NbProduits = produitsEnCache.Count;
      ViewBag.TaillePage = TaillePage;

      return View( "Index", produitsTrieesEtPaginés );
    }

    public ActionResult Supprimer( Product victime, string tri, int page, string filtre ) {
      if( Request.HttpMethod == "GET" || victime.ProductID == 0 )
        return Index( tri, filtre, page );
      victime.UnitPrice = 1234.01m;
      DC.Entry<Product>( victime ).State = System.Data.Entity.EntityState.Deleted;
      try {
        DC.SaveChanges();
        ViewBag.Message = String.Format("Confirmation : le produit N°{0} à {1:0.00}$ est supprimé", victime.ProductID, victime.UnitPrice );
        return Index( tri, filtre, page, forcerLaRequeteEnBase: true );
      }
      catch( DbUpdateConcurrencyException cac ) {
        var erreur = cac.Entries.Single();
        var nvValeurs = erreur.GetDatabaseValues();
        ViewBag.Message = string.Format(
          "Le prix du produit '{0}' a changé ({1} => {2}). Suppression abandonnée.",
          nvValeurs["ProductName"], victime.UnitPrice, nvValeurs["UnitPrice"] );
        DC.Entry( victime ).State = System.Data.Entity.EntityState.Detached;
        return Index( tri, filtre, page, forcerLaRequeteEnBase: true );
      }
    }

    protected override void Dispose( bool disposing ) {
			if( disposing )
				DC.Dispose();
      base.Dispose( disposing );
    }
  }
}