using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Conventions;
using MongoDB.Bson.Serialization.Serializers;

using Core.DomainObjects;
using Core.DomainObjects.Pages;
using Core.DomainObjects.PageSections;
using Core.DomainObjects.Documents;
using Core.DomainObjects.L10n;
using DataProviders.Converters;
using Core.Enumerations;

namespace DataProviders {
  public class Mappings {

    public static void RegisterClassMap() {
      ConventionRegistry.Register("MyConventions",
        new ConventionPack {
          new CamelCaseElementNameConvention(),
          new IgnoreIfNullConvention(true)
        }, type => true);

      // https://kevsoft.net/2020/06/25/storing-guids-as-strings-in-mongodb-with-csharp.html
      BsonSerializer.RegisterSerializer(new GuidSerializer(BsonType.String));
      // https://kevsoft.net/2020/07/02/how-to-store-decimal-fields-in-mongodb-with-csharp.html
      BsonSerializer.RegisterSerializer(new DecimalSerializer(BsonType.Decimal128));

      #region L10n
      if (!BsonClassMap.IsClassMapRegistered(typeof(PostItemL10n))) {
        BsonClassMap.RegisterClassMap<PostItemL10n>(cm => {
          cm.AutoMap();

          cm.GetMemberMap(c => c.Locale)
            .SetSerializer(new EnumerationSerializer<Locales>());

          cm.GetMemberMap(c => c.TextFormat)
            .SetSerializer(new EnumerationSerializer<TextFormat>());
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(MediaAttachmentL10n))) {
        BsonClassMap.RegisterClassMap<MediaAttachmentL10n>(cm => {
          cm.AutoMap();

          cm.GetMemberMap(c => c.Locale)
            .SetSerializer(new EnumerationSerializer<Locales>());
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(CategoryL10n))) {
        BsonClassMap.RegisterClassMap<CategoryL10n>(cm => {
          cm.AutoMap();

          cm.GetMemberMap(c => c.Locale)
            .SetSerializer(new EnumerationSerializer<Locales>());
        });
      }
      #endregion

      #region Primitives
      if (!BsonClassMap.IsClassMapRegistered(typeof(Address))) {
        BsonClassMap.RegisterClassMap<Address>(cm => {
          cm.AutoMap();
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(Author))) {
        BsonClassMap.RegisterClassMap<Author>(cm => {
          cm.AutoMap();
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(Category))) {
        BsonClassMap.RegisterClassMap<Category>(cm => {
          cm.AutoMap();
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(Comment))) {
        BsonClassMap.RegisterClassMap<Comment>(cm => {
          cm.AutoMap();
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(Contact))) {
        BsonClassMap.RegisterClassMap<Contact>(cm => {
          cm.AutoMap();

          cm.GetMemberMap(c => c.ContactType)
            .SetSerializer(new EnumerationSerializer<ContactTypes>());
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(Feature))) {
        BsonClassMap.RegisterClassMap<Feature>(cm => {
          cm.AutoMap();
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(FormItem))) {
        BsonClassMap.RegisterClassMap<FormItem>(cm => {
          cm.AutoMap();
        });
      }


      if (!BsonClassMap.IsClassMapRegistered(typeof(Header))) {
        BsonClassMap.RegisterClassMap<Header>(cm => {
          cm.AutoMap();
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(MediaAttachment))) {
        BsonClassMap.RegisterClassMap<MediaAttachment>(cm => {
          cm.AutoMap();
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(Link))) {
        BsonClassMap.RegisterClassMap<Link>(cm => {
          cm.AutoMap();
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(Localization))) {
        BsonClassMap.RegisterClassMap<Localization>(cm => {
          cm.AutoMap();
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(MenuItem))) {
        BsonClassMap.RegisterClassMap<MenuItem>(cm => {
          cm.AutoMap();
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(Reviewer))) {
        BsonClassMap.RegisterClassMap<Reviewer>(cm => {
          cm.AutoMap();

          cm.SetIsRootClass(true);
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(Passwords))) {
        BsonClassMap.RegisterClassMap<Passwords>(cm => {
          cm.AutoMap();
        });
      }


      if (!BsonClassMap.IsClassMapRegistered(typeof(Route))) {
        BsonClassMap.RegisterClassMap<Route>(cm => {
          cm.AutoMap();
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(Testimonial))) {
        BsonClassMap.RegisterClassMap<Testimonial>(cm => {
          cm.AutoMap();
        });
      }
      #endregion


      #region BlogItem
      if (!BsonClassMap.IsClassMapRegistered(typeof(BlogItem))) {
        BsonClassMap.RegisterClassMap<BlogItem>(cm => {
          cm.AutoMap();
        });
      }
      #endregion

      #region ShopItem
      if (!BsonClassMap.IsClassMapRegistered(typeof(ShopItem))) {
        BsonClassMap.RegisterClassMap<ShopItem>(cm => {
          cm.AutoMap();
        });
      }
      #endregion


      #region PageSections
      if (!BsonClassMap.IsClassMapRegistered(typeof(BillingAddressSection))) {
        BsonClassMap.RegisterClassMap<BillingAddressSection>(cm => {
          cm.AutoMap();
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(CallToActionSection))) {
        BsonClassMap.RegisterClassMap<CallToActionSection>(cm => {
          cm.AutoMap();
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(CommentsSection))) {
        BsonClassMap.RegisterClassMap<CommentsSection>(cm => {
          cm.AutoMap();
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(FeaturedBlogSection))) {
        BsonClassMap.RegisterClassMap<FeaturedBlogSection>(cm => {
          cm.AutoMap();
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(FeaturedBlogSection))) {
        BsonClassMap.RegisterClassMap<FeaturedBlogSection>(cm => {
          cm.AutoMap();
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(FeaturesSection))) {
        BsonClassMap.RegisterClassMap<FeaturesSection>(cm => {
          cm.AutoMap();
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(PaymentSection))) {
        BsonClassMap.RegisterClassMap<PaymentSection>(cm => {
          cm.AutoMap();
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(ProductSection))) {
        BsonClassMap.RegisterClassMap<ProductSection>(cm => {
          cm.AutoMap();
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(ProductsSection))) {
        BsonClassMap.RegisterClassMap<ProductsSection>(cm => {
          cm.AutoMap();
        });
      }
      
      if (!BsonClassMap.IsClassMapRegistered(typeof(RelatedProductsSection))) {
        BsonClassMap.RegisterClassMap<RelatedProductsSection>(cm => {
          cm.AutoMap();
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(SettingsSection))) {
        BsonClassMap.RegisterClassMap<SettingsSection>(cm => {
          cm.AutoMap();
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(ShippingAddressSection))) {
        BsonClassMap.RegisterClassMap<ShippingAddressSection>(cm => {
          cm.AutoMap();
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(ShopItemsSection))) {
        BsonClassMap.RegisterClassMap<ShopItemsSection>(cm => {
          cm.AutoMap();
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(SummarySection))) {
        BsonClassMap.RegisterClassMap<SummarySection>(cm => {
          cm.AutoMap();
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(TestimonialsSection))) {
        BsonClassMap.RegisterClassMap<TestimonialsSection>(cm => {
          cm.AutoMap();
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(TitleSection))) {
        BsonClassMap.RegisterClassMap<TitleSection>(cm => {
          cm.AutoMap();
        });
      }
      #endregion

      #region Pages
      if (!BsonClassMap.IsClassMapRegistered(typeof(BlogCatalogPage))) {
        BsonClassMap.RegisterClassMap<BlogCatalogPage>(cm => {
          cm.AutoMap();
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(BlogItemPage))) {
        BsonClassMap.RegisterClassMap<BlogItemPage>(cm => {
          cm.AutoMap();
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(HomePage))) {
        BsonClassMap.RegisterClassMap<HomePage>(cm => {
          cm.AutoMap();
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(ShopCartPage))) {
        BsonClassMap.RegisterClassMap<ShopCartPage>(cm => {
          cm.AutoMap();
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(ShopCatalogPage))) {
        BsonClassMap.RegisterClassMap<ShopCatalogPage>(cm => {
          cm.AutoMap();
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(ShopCheckoutPage))) {
        BsonClassMap.RegisterClassMap<ShopCheckoutPage>(cm => {
          cm.AutoMap();
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(ShopItemPage))) {
        BsonClassMap.RegisterClassMap<ShopItemPage>(cm => {
          cm.AutoMap();
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(SignInPage))) {
        BsonClassMap.RegisterClassMap<SignInPage>(cm => {
          cm.AutoMap();
        });
      }

      if (!BsonClassMap.IsClassMapRegistered(typeof(SignUpPage))) {
        BsonClassMap.RegisterClassMap<SignUpPage>(cm => {
          cm.AutoMap();
        });
      }
      #endregion


      #region Content
      if (!BsonClassMap.IsClassMapRegistered(typeof(Content))) {
        BsonClassMap.RegisterClassMap<Content>(cm => {
          cm.AutoMap();

          //cm.GetMemberMap(c => c.Event)
          //  .SetSerializer(new EnumerationSerializer<StateEvent>());
        });
      }
      #endregion


      



      #region User
      if (!BsonClassMap.IsClassMapRegistered(typeof(User))) {
        BsonClassMap.RegisterClassMap<User>(cm => {
          cm.AutoMap();
        });
      }
      #endregion
    }
  }
}
