content: /*******************************************************************************
   * Copyright (C) 2021, 1C-Soft LLC and others.
   *
   * This program and the accompanying materials are made
   * available under the terms of the Eclipse Public License 2.0
   * which is available at https://www.eclipse.org/legal/epl-2.0/
   *
   * SPDX-License-Identifier: EPL-2.0
   *
   * Contributors:
   *     1C-Soft LLC - initial API and implementation
   *******************************************************************************/
  package com.e1c.v8codestyle.internal.bsl;
  
  import static com.e1c.v8codestyle.bsl.strict.StrictTypeUtil.BSL_FILE_EXTENSION;
  
  import java.io.InputStream;
  import java.net.URL;
  import java.text.MessageFormat;
  import java.util.Collection;
  import java.util.Optional;
  import java.util.function.Supplier;
  import java.util.stream.Collectors;
  
  import org.eclipse.core.resources.IFile;
  import org.eclipse.core.resources.IProject;
  import org.eclipse.core.resources.ProjectScope;
  import org.eclipse.core.runtime.CoreException;
  import org.eclipse.core.runtime.IPath;
  import org.eclipse.core.runtime.IStatus;
  import org.eclipse.core.runtime.Platform;
  import org.eclipse.core.runtime.preferences.ConfigurationScope;
  import org.eclipse.core.runtime.preferences.DefaultScope;
  import org.eclipse.core.runtime.preferences.IScopeContext;
  import org.eclipse.core.runtime.preferences.InstanceScope;
  
  import com._1c.g5.v8.dt.bsl.model.ModuleType;
  import com._1c.g5.v8.dt.metadata.mdclass.ScriptVariant;
  import com.e1c.v8codestyle.bsl.IModuleStructureProvider;
  import com.e1c.v8codestyle.bsl.ModuleStructure;
  import com.google.common.collect.ImmutableSet;
  
  /**
   * The default implementation of module structure provider.
   *
   * @author Dmitriy Marmyshev
   */
  public class ModuleStructureProvider
      implements IModuleStructureProvider
  {
  
      private static final String FOLDER_RU = "/templates/ru/"; //$NON-NLS-1$
  
      private static final String FOLDER_EN = "/templates/en/"; //$NON-NLS-1$
  
      private static final String REUSABLE_SUFFIX = "_reusable"; //$NON-NLS-1$
  
      private static final IPath FOLDER_SETTINGS = new org.eclipse.core.runtime.Path(".settings/templates"); //$NON-NLS-1$
  
      @Override
      public boolean canCreateStructure(IProject project)
      {
          ProjectScope scope = new ProjectScope(project);
          IScopeContext[] contexts =
              new IScopeContext[] { scope, InstanceScope.INSTANCE, ConfigurationScope.INSTANCE, DefaultScope.INSTANCE };
  
          return Platform.getPreferencesService()
              .getBoolean(PREF_QUALIFIER, PREF_KEY_CREATE_STRUCTURE, PREF_DEFAULT_CREATE_STRUCTURE, contexts);
      }
  
      @Override
      public Supplier<InputStream> getModuleStructureTemplate(IProject project, ModuleType moduleType,
          boolean reusableModule, ScriptVariant script)
      {
          if (moduleType == null || script == null)
          {
              return null;
          }
  
          StringBuilder sb = new StringBuilder();
          sb.append(moduleType.getName().toLowerCase());
          if (reusableModule)
          {
              sb.append(REUSABLE_SUFFIX);
          }
          sb.append("."); //$NON-NLS-1$
          sb.append(BSL_FILE_EXTENSION);
  
          IFile templateFile = project.getFile(FOLDER_SETTINGS.append(sb.toString()));
  
          if (script == ScriptVariant.ENGLISH)
          {
              sb.insert(0, FOLDER_EN);
          }
          else
          {
              sb.insert(0, FOLDER_RU);
          }
          String path = sb.toString();
  
          if (templateFile.exists())
          {
              return () -> {
                  try
                  {
                      return templateFile.getContents();
                  }
                  catch (CoreException e)
                  {
                      IStatus message =
                          BslPlugin.createErrorStatus("Cannot read tempate file " + templateFile.toString(), e); //$NON-NLS-1$
                      BslPlugin.log(message);
                  }
                  return getClass().getResourceAsStream(path);
              };
          }
  
          Optional<URL> template = getBundleEntry(path);
          if (template.isPresent())
          {
              return () -> getClass().getResourceAsStream(path);
          }
          String message = MessageFormat.format("Cannot find module template for type: {0} and language: {1} in {2}", //$NON-NLS-1$
              moduleType.getName(), script, path);
          IStatus status = BslPlugin.createWarningStatus(message);
          BslPlugin.log(status);
          return null;
  
      }
  
      private Optional<URL> getBundleEntry(String path)
      {
          URL url = getClass().getResource(path);
          return Optional.ofNullable(url);
      }
  
      @Override
      public Collection<String> getModuleStructureRegions(ModuleType moduleType, ScriptVariant scriptVariant)
      {
          return ImmutableSet.copyOf(ModuleStructure.getStructureByType(moduleType)
              .stream()
              .map(s -> s.getName(scriptVariant))
              .collect(Collectors.toList()));
      }
  }
  