@Override
  public void saveCustomShippingConfiguration(
      String moduleCode, CustomIntegrationConfiguration shippingConfiguration, MerchantStore store)
      throws ServiceException {

    ShippingQuoteModule quoteModule = (ShippingQuoteModule) shippingModules.get(moduleCode);
    if (quoteModule == null) {
      throw new ServiceException("Shipping module " + moduleCode + " does not exist");
    }

    String configurationValue = shippingConfiguration.toJSONString();

    try {

      MerchantConfiguration configuration =
          merchantConfigurationService.getMerchantConfiguration(moduleCode, store);

      if (configuration == null) {

        configuration = new MerchantConfiguration();
        configuration.setKey(moduleCode);
        configuration.setMerchantStore(store);
      }
      configuration.setValue(configurationValue);
      merchantConfigurationService.saveOrUpdate(configuration);

    } catch (Exception e) {
      throw new IntegrationException(e);
    }
  }
  @Override
  public void setSupportedCountries(MerchantStore store, List<String> countryCodes)
      throws ServiceException {

    // transform a list of string to json entry
    ObjectMapper mapper = new ObjectMapper();

    try {
      String value = mapper.writeValueAsString(countryCodes);

      MerchantConfiguration configuration =
          merchantConfigurationService.getMerchantConfiguration(SUPPORTED_COUNTRIES, store);

      if (configuration == null) {
        configuration = new MerchantConfiguration();
        configuration.setKey(SUPPORTED_COUNTRIES);
        configuration.setMerchantStore(store);
      }

      configuration.setValue(value);

      merchantConfigurationService.saveOrUpdate(configuration);

    } catch (Exception e) {
      throw new ServiceException(e);
    }
  }
  @Override
  public void removeShippingQuoteModuleConfiguration(String moduleCode, MerchantStore store)
      throws ServiceException {

    try {
      Map<String, IntegrationConfiguration> modules =
          new HashMap<String, IntegrationConfiguration>();
      MerchantConfiguration merchantConfiguration =
          merchantConfigurationService.getMerchantConfiguration(SHIPPING_MODULES, store);
      if (merchantConfiguration != null) {
        if (!StringUtils.isBlank(merchantConfiguration.getValue())) {
          String decrypted = encryption.decrypt(merchantConfiguration.getValue());
          modules = ConfigurationModulesLoader.loadIntegrationConfigurations(decrypted);
        }

        modules.remove(moduleCode);
        String configs = ConfigurationModulesLoader.toJSONString(modules);
        String encrypted = encryption.encrypt(configs);
        merchantConfiguration.setValue(encrypted);
        merchantConfigurationService.saveOrUpdate(merchantConfiguration);
      }

      MerchantConfiguration configuration =
          merchantConfigurationService.getMerchantConfiguration(moduleCode, store);

      if (configuration != null) { // custom module

        merchantConfigurationService.delete(configuration);
      }

    } catch (Exception e) {
      throw new ServiceException(e);
    }
  }
 @PreAuthorize("hasRole('AUTH')")
 @RequestMapping(
     value = "/admin/configuration/saveConfiguration.html",
     method = RequestMethod.POST)
 public String saveConfigurations(
     @ModelAttribute("configuration") ConfigListWrapper configWrapper,
     BindingResult result,
     Model model,
     HttpServletRequest request,
     Locale locale)
     throws Exception {
   setConfigurationMenu(model, request);
   List<MerchantConfiguration> configs = configWrapper.getMerchantConfigs();
   MerchantStore store = (MerchantStore) request.getAttribute(Constants.ADMIN_STORE);
   for (MerchantConfiguration mConfigs : configs) {
     mConfigs.setMerchantStore(store);
     if (!StringUtils.isBlank(mConfigs.getValue())) {
       mConfigs.setMerchantConfigurationType(MerchantConfigurationType.CONFIG);
       merchantConfigurationService.saveOrUpdate(mConfigs);
     } else { // remove if submited blank and exists
       MerchantConfiguration config =
           merchantConfigurationService.getMerchantConfiguration(mConfigs.getKey(), store);
       if (config != null) {
         merchantConfigurationService.delete(config);
       }
     }
   }
   model.addAttribute("success", "success");
   model.addAttribute("configuration", configWrapper);
   return com.salesmanager.web.admin.controller.ControllerConstants.Tiles.Configuration.accounts;
 }
  @Override
  public void saveShippingConfiguration(
      ShippingConfiguration shippingConfiguration, MerchantStore store) throws ServiceException {

    MerchantConfiguration configuration =
        merchantConfigurationService.getMerchantConfiguration(
            ShippingConstants.SHIPPING_CONFIGURATION, store);

    if (configuration == null) {
      configuration = new MerchantConfiguration();
      configuration.setMerchantStore(store);
      configuration.setKey(ShippingConstants.SHIPPING_CONFIGURATION);
    }

    String value = shippingConfiguration.toJSONString();
    configuration.setValue(value);
    merchantConfigurationService.saveOrUpdate(configuration);
  }
  @Override
  public List<Country> getShipToCountryList(MerchantStore store, Language language)
      throws ServiceException {

    ShippingConfiguration shippingConfiguration = getShippingConfiguration(store);
    ShippingType shippingType = ShippingType.INTERNATIONAL;
    List<String> supportedCountries = new ArrayList<String>();
    if (shippingConfiguration == null) {
      shippingConfiguration = new ShippingConfiguration();
    }

    if (shippingConfiguration.getShippingType() != null) {
      shippingType = shippingConfiguration.getShippingType();
    }

    if (shippingType.name().equals(ShippingType.NATIONAL.name())) {

      supportedCountries.add(store.getCountry().getIsoCode());

    } else {

      MerchantConfiguration configuration =
          merchantConfigurationService.getMerchantConfiguration(SUPPORTED_COUNTRIES, store);

      if (configuration != null) {

        String countries = configuration.getValue();
        if (!StringUtils.isBlank(countries)) {

          Object objRegions = JSONValue.parse(countries);
          JSONArray arrayRegions = (JSONArray) objRegions;
          @SuppressWarnings("rawtypes")
          Iterator i = arrayRegions.iterator();
          while (i.hasNext()) {
            supportedCountries.add((String) i.next());
          }
        }
      }
    }

    return countryService.getCountries(supportedCountries, language);
  }
  @Override
  public Map<String, IntegrationConfiguration> getShippingModulesConfigured(MerchantStore store)
      throws ServiceException {
    try {

      Map<String, IntegrationConfiguration> modules =
          new HashMap<String, IntegrationConfiguration>();
      MerchantConfiguration merchantConfiguration =
          merchantConfigurationService.getMerchantConfiguration(SHIPPING_MODULES, store);
      if (merchantConfiguration != null) {
        if (!StringUtils.isBlank(merchantConfiguration.getValue())) {
          String decrypted = encryption.decrypt(merchantConfiguration.getValue());
          modules = ConfigurationModulesLoader.loadIntegrationConfigurations(decrypted);
        }
      }
      return modules;

    } catch (Exception e) {
      throw new ServiceException(e);
    }
  }
  @Override
  public ShippingConfiguration getShippingConfiguration(MerchantStore store)
      throws ServiceException {

    MerchantConfiguration configuration =
        merchantConfigurationService.getMerchantConfiguration(
            ShippingConstants.SHIPPING_CONFIGURATION, store);

    ShippingConfiguration shippingConfiguration = null;

    if (configuration != null) {
      String value = configuration.getValue();

      ObjectMapper mapper = new ObjectMapper();
      try {
        shippingConfiguration = mapper.readValue(value, ShippingConfiguration.class);
      } catch (Exception e) {
        throw new ServiceException("Cannot parse json string " + value);
      }
    }
    return shippingConfiguration;
  }
  @Override
  public List<String> getSupportedCountries(MerchantStore store) throws ServiceException {

    List<String> supportedCountries = new ArrayList<String>();
    MerchantConfiguration configuration =
        merchantConfigurationService.getMerchantConfiguration(SUPPORTED_COUNTRIES, store);

    if (configuration != null) {

      String countries = configuration.getValue();
      if (!StringUtils.isBlank(countries)) {

        Object objRegions = JSONValue.parse(countries);
        JSONArray arrayRegions = (JSONArray) objRegions;
        @SuppressWarnings("rawtypes")
        Iterator i = arrayRegions.iterator();
        while (i.hasNext()) {
          supportedCountries.add((String) i.next());
        }
      }
    }

    return supportedCountries;
  }
  @Override
  public void saveShippingQuoteModuleConfiguration(
      IntegrationConfiguration configuration, MerchantStore store) throws ServiceException {

    // validate entries
    try {

      String moduleCode = configuration.getModuleCode();
      ShippingQuoteModule quoteModule = (ShippingQuoteModule) shippingModules.get(moduleCode);
      if (quoteModule == null) {
        throw new ServiceException("Shipping quote module " + moduleCode + " does not exist");
      }
      quoteModule.validateModuleConfiguration(configuration, store);

    } catch (IntegrationException ie) {
      throw ie;
    }

    try {
      Map<String, IntegrationConfiguration> modules =
          new HashMap<String, IntegrationConfiguration>();
      MerchantConfiguration merchantConfiguration =
          merchantConfigurationService.getMerchantConfiguration(SHIPPING_MODULES, store);
      if (merchantConfiguration != null) {
        if (!StringUtils.isBlank(merchantConfiguration.getValue())) {

          String decrypted = encryption.decrypt(merchantConfiguration.getValue());
          modules = ConfigurationModulesLoader.loadIntegrationConfigurations(decrypted);
        }
      } else {
        merchantConfiguration = new MerchantConfiguration();
        merchantConfiguration.setMerchantStore(store);
        merchantConfiguration.setKey(SHIPPING_MODULES);
      }
      modules.put(configuration.getModuleCode(), configuration);

      String configs = ConfigurationModulesLoader.toJSONString(modules);

      String encrypted = encryption.encrypt(configs);
      merchantConfiguration.setValue(encrypted);
      merchantConfigurationService.saveOrUpdate(merchantConfiguration);

    } catch (Exception e) {
      throw new ServiceException(e);
    }
  }
  @PreAuthorize("hasRole('AUTH')")
  @RequestMapping(value = "/admin/configuration/accounts.html", method = RequestMethod.GET)
  public String displayAccountsConfguration(
      Model model, HttpServletRequest request, HttpServletResponse response) throws Exception {

    setConfigurationMenu(model, request);
    List<MerchantConfiguration> configs = new ArrayList<MerchantConfiguration>();
    MerchantStore store = (MerchantStore) request.getAttribute(Constants.ADMIN_STORE);
    MerchantConfiguration merchantFBConfiguration =
        merchantConfigurationService.getMerchantConfiguration(
            Constants.KEY_FACEBOOK_PAGE_URL, store);
    if (null == merchantFBConfiguration) {
      merchantFBConfiguration = new MerchantConfiguration();
      merchantFBConfiguration.setKey(Constants.KEY_FACEBOOK_PAGE_URL);
      merchantFBConfiguration.setMerchantConfigurationType(MerchantConfigurationType.CONFIG);
    }
    configs.add(merchantFBConfiguration);

    MerchantConfiguration merchantGoogleAnalyticsConfiguration =
        merchantConfigurationService.getMerchantConfiguration(
            Constants.KEY_GOOGLE_ANALYTICS_URL, store);
    if (null == merchantGoogleAnalyticsConfiguration) {
      merchantGoogleAnalyticsConfiguration = new MerchantConfiguration();
      merchantGoogleAnalyticsConfiguration.setKey(Constants.KEY_GOOGLE_ANALYTICS_URL);
      merchantGoogleAnalyticsConfiguration.setMerchantConfigurationType(
          MerchantConfigurationType.CONFIG);
    }
    configs.add(merchantGoogleAnalyticsConfiguration);

    MerchantConfiguration merchantInstagramConfiguration =
        merchantConfigurationService.getMerchantConfiguration(Constants.KEY_INSTAGRAM_URL, store);
    if (null == merchantInstagramConfiguration) {
      merchantInstagramConfiguration = new MerchantConfiguration();
      merchantInstagramConfiguration.setKey(Constants.KEY_INSTAGRAM_URL);
      merchantInstagramConfiguration.setMerchantConfigurationType(MerchantConfigurationType.CONFIG);
    }
    configs.add(merchantInstagramConfiguration);

    MerchantConfiguration merchantPinterestConfiguration =
        merchantConfigurationService.getMerchantConfiguration(
            Constants.KEY_PINTEREST_PAGE_URL, store);
    if (null == merchantPinterestConfiguration) {
      merchantPinterestConfiguration = new MerchantConfiguration();
      merchantPinterestConfiguration.setKey(Constants.KEY_PINTEREST_PAGE_URL);
      merchantPinterestConfiguration.setMerchantConfigurationType(MerchantConfigurationType.CONFIG);
    }
    configs.add(merchantPinterestConfiguration);

    /**
     * MerchantConfiguration merchantGoogleApiConfiguration =
     * merchantConfigurationService.getMerchantConfiguration(Constants.KEY_GOOGLE_API_KEY,store);
     * if(null == merchantGoogleApiConfiguration) { merchantGoogleApiConfiguration = new
     * MerchantConfiguration(); merchantGoogleApiConfiguration.setKey(Constants.KEY_GOOGLE_API_KEY);
     * merchantGoogleApiConfiguration.setMerchantConfigurationType(MerchantConfigurationType.CONFIG);
     * } configs.add(merchantGoogleApiConfiguration);
     */
    MerchantConfiguration twitterConfiguration =
        merchantConfigurationService.getMerchantConfiguration(Constants.KEY_TWITTER_HANDLE, store);
    if (null == twitterConfiguration) {
      twitterConfiguration = new MerchantConfiguration();
      twitterConfiguration.setKey(Constants.KEY_TWITTER_HANDLE);
      twitterConfiguration.setMerchantConfigurationType(MerchantConfigurationType.CONFIG);
    }
    configs.add(twitterConfiguration);

    ConfigListWrapper configWrapper = new ConfigListWrapper();
    configWrapper.setMerchantConfigs(configs);
    model.addAttribute("configuration", configWrapper);

    return com.salesmanager.web.admin.controller.ControllerConstants.Tiles.Configuration.accounts;
  }