content: package com.termux.x11.controller.container;
  
  import android.os.Environment;
  
  import com.termux.x11.controller.core.EnvVars;
  import com.termux.x11.controller.core.FileUtils;
  import com.termux.x11.controller.core.KeyValueSet;
  import com.termux.x11.controller.core.WineInfo;
  import com.termux.x11.controller.core.WineThemeManager;
  
  import org.json.JSONException;
  import org.json.JSONObject;
  
  import java.io.File;
  import java.util.Iterator;
  
  public class Container {
      public static final String DEFAULT_ENV_VARS = "ZINK_DESCRIPTORS=lazy ZINK_CONTEXT_THREADED=true ZINK_DEBUG=compact MESA_SHADER_CACHE_DISABLE=false MESA_SHADER_CACHE_MAX_SIZE=512MB mesa_glthread=true WINEESYNC=1";
      public static final String DEFAULT_SCREEN_SIZE = "800x600";
      public static final String DEFAULT_GRAPHICS_DRIVER = "turnip";
      public static final String DEFAULT_AUDIO_DRIVER = "alsa";
      public static final String DEFAULT_DXWRAPPER = "wined3d";
      public static final String DEFAULT_WINCOMPONENTS = "direct3d=1,directsound=1,directmusic=0,directshow=0,directplay=0,vcrun2010=1";
      public static final String FALLBACK_WINCOMPONENTS = "direct3d=0,directsound=0,directmusic=0,directshow=0,directplay=0,vcrun2010=0";
      public static final String DEFAULT_DRIVES = "D:"+Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)+"E:/data/data/com.winlator/storage";
      public static final byte MAX_DRIVE_LETTERS = 8;
      public final int id;
      private String name;
      private String screenSize = DEFAULT_SCREEN_SIZE;
      private String envVars = DEFAULT_ENV_VARS;
      private String graphicsDriver = DEFAULT_GRAPHICS_DRIVER;
      private String dxwrapper = DEFAULT_DXWRAPPER;
      private String dxwrapperConfig = "";
      private String graphicsDriverConfig = "";
      private String wincomponents = DEFAULT_WINCOMPONENTS;
      private String audioDriver = DEFAULT_AUDIO_DRIVER;
      private String drives = DEFAULT_DRIVES;
      private String wineVersion = WineInfo.MAIN_WINE_VERSION.identifier();
      private boolean showFPS;
      private boolean stopServicesOnStartup = true;
      private String cpuList;
      private String desktopTheme = WineThemeManager.DEFAULT_DESKTOP_THEME;
      private File rootDir;
      private JSONObject extraData;
  
      public Container(int id) {
          this.id = id;
          this.name = "Container-"+id;
      }
  
      public String getName() {
          return name;
      }
  
      public void setName(String name) {
          this.name = name;
      }
  
      public String getScreenSize() {
          return screenSize;
      }
  
      public void setScreenSize(String screenSize) {
          this.screenSize = screenSize;
      }
  
      public String getEnvVars() {
          return envVars;
      }
  
      public void setEnvVars(String envVars) {
          this.envVars = envVars != null ? envVars : "";
      }
  
      public String getGraphicsDriver() {
          return graphicsDriver;
      }
  
      public void setGraphicsDriver(String graphicsDriver) {
          this.graphicsDriver = graphicsDriver;
      }
  
      public String getDXWrapper() {
          return dxwrapper;
      }
  
      public void setDXWrapper(String dxwrapper) {
          this.dxwrapper = dxwrapper;
      }
  
      public String getDXWrapperConfig() {
          return dxwrapperConfig;
      }
  
      public void setDXWrapperConfig(String dxwrapperConfig) {
          this.dxwrapperConfig = dxwrapperConfig != null ? dxwrapperConfig : "";
      }
  
      public String getGraphicsDriverConfig() {
          return graphicsDriverConfig;
      }
  
      public void setGraphicsDriverConfig(String graphicsDriverConfig) {
          this.graphicsDriverConfig = graphicsDriverConfig != null ? graphicsDriverConfig : "";
      }
  
      public String getAudioDriver() {
          return audioDriver;
      }
  
      public void setAudioDriver(String audioDriver) {
          this.audioDriver = audioDriver;
      }
  
      public String getWinComponents() {
          return wincomponents;
      }
  
      public void setWinComponents(String wincomponents) {
          this.wincomponents = wincomponents;
      }
  
      public String getDrives() {
          return drives;
      }
  
      public void setDrives(String drives) {
          this.drives = drives;
      }
  
      public boolean isShowFPS() {
          return showFPS;
      }
  
      public void setShowFPS(boolean showFPS) {
          this.showFPS = showFPS;
      }
  
      public boolean isStopServicesOnStartup() {
          return stopServicesOnStartup;
      }
  
      public void setStopServicesOnStartup(boolean stopServicesOnStartup) {
          this.stopServicesOnStartup = stopServicesOnStartup;
      }
  
      public String getCPUList() {
          return cpuList;
      }
  
      public void setCPUList(String cpuList) {
          this.cpuList = cpuList != null && !cpuList.isEmpty() ? cpuList : null;
      }
  
  
  
  
  
  
      public File getRootDir() {
          return rootDir;
      }
  
      public void setRootDir(File rootDir) {
          this.rootDir = rootDir;
      }
  
      public void setExtraData(JSONObject extraData) {
          this.extraData = extraData;
      }
  
      public String getExtra(String name) {
          return getExtra(name, "");
      }
  
      public String getExtra(String name, String fallback) {
          try {
              return extraData != null && extraData.has(name) ? extraData.getString(name) : fallback;
          }
          catch (JSONException e) {
              return fallback;
          }
      }
  
      public void putExtra(String name, Object value) {
          if (extraData == null) extraData = new JSONObject();
          try {
              if (value != null) {
                  extraData.put(name, value);
              }
              else extraData.remove(name);
          }
          catch (JSONException e) {}
      }
  
      public String getWineVersion() {
          return wineVersion;
      }
  
      public void setWineVersion(String wineVersion) {
          this.wineVersion = wineVersion;
      }
  
      public File getConfigFile() {
          return new File(rootDir, ".container");
      }
  
  
      public File getStartMenuDir() {
          return new File(rootDir, ".wine/drive_c/ProgramData/Microsoft/Windows/Start Menu/");
      }
  
      public File getIconsDir(int size) {
          return new File(rootDir, ".local/share/icons/hicolor/"+size+"x"+size+"/apps/");
      }
  
      public String getDesktopTheme() {
          return desktopTheme;
      }
  
      public void setDesktopTheme(String desktopTheme) {
          this.desktopTheme = desktopTheme;
      }
  
      public Iterable<String[]> drivesIterator() {
          return drivesIterator(drives);
      }
  
      public static Iterable<String[]> drivesIterator(final String drives) {
          final int[] index = {drives.indexOf(":")};
          final String[] item = new String[2];
          return () -> new Iterator<String[]>() {
              @Override
              public boolean hasNext() {
                  return index[0] != -1;
              }
  
              @Override
              public String[] next() {
                  item[0] = String.valueOf(drives.charAt(index[0]-1));
                  int nextIndex = drives.indexOf(":", index[0]+1);
                  item[1] = drives.substring(index[0]+1, nextIndex != -1 ? nextIndex-1 : drives.length());
                  index[0] = nextIndex;
                  return item;
              }
          };
      }
  
      public void saveData() {
          try {
              JSONObject data = new JSONObject();
              data.put("id", id);
              data.put("name", name);
              data.put("screenSize", screenSize);
              data.put("envVars", envVars);
              data.put("cpuList", cpuList);
              data.put("graphicsDriver", graphicsDriver);
              data.put("dxwrapper", dxwrapper);
              if (!dxwrapperConfig.isEmpty()) data.put("dxwrapperConfig", dxwrapperConfig);
              if (!graphicsDriverConfig.isEmpty()) data.put("graphicsDriverConfig", graphicsDriverConfig);
              data.put("audioDriver", audioDriver);
              data.put("wincomponents", wincomponents);
              data.put("drives", drives);
              data.put("showFPS", showFPS);
              data.put("stopServicesOnStartup", stopServicesOnStartup);
              data.put("desktopTheme", desktopTheme);
              data.put("extraData", extraData);
  
              if (!wineVersion.equals(WineInfo.MAIN_WINE_VERSION.identifier())) {
                  data.put("wineVersion", wineVersion);
              }
  
              FileUtils.writeString(getConfigFile(), data.toString());
          }
          catch (JSONException e) {}
      }
  
      public void loadData(JSONObject data) throws JSONException {
          wineVersion = WineInfo.MAIN_WINE_VERSION.identifier();
          dxwrapperConfig = "";
          graphicsDriverConfig = "";
          checkObsoleteOrMissingProperties(data);
  
          for (Iterator<String> it = data.keys(); it.hasNext(); ) {
              String key = it.next();
              switch (key) {
                  case "name" :
                      setName(data.getString(key));
                      break;
                  case "screenSize" :
                      setScreenSize(data.getString(key));
                      break;
                  case "envVars" :
                      setEnvVars(data.getString(key));
                      break;
                  case "cpuList" :
                      setCPUList(data.getString(key));
                      break;
                  case "graphicsDriver" :
                      setGraphicsDriver(data.getString(key));
                      break;
                  case "wincomponents" :
                      setWinComponents(data.getString(key));
                      break;
                  case "dxwrapper" :
                      setDXWrapper(data.getString(key));
                      break;
                  case "dxwrapperConfig" :
                      setDXWrapperConfig(data.getString(key));
                      break;
                  case "graphicsDriverConfig" :
                      setGraphicsDriverConfig(data.getString(key));
                      break;
                  case "drives" :
                      setDrives(data.getString(key));
                      break;
                  case "showFPS" :
                      setShowFPS(data.getBoolean(key));
                      break;
                  case "stopServicesOnStartup" :
                      setStopServicesOnStartup(data.getBoolean(key));
                      break;
                  case "extraData" : {
                      JSONObject extraData = data.getJSONObject(key);
                      checkObsoleteOrMissingProperties(extraData);
                      setExtraData(extraData);
                      break;
                  }
                  case "wineVersion" :
                      setWineVersion(data.getString(key));
                      break;
                  case "audioDriver" :
                      setAudioDriver(data.getString(key));
                      break;
                  case "desktopTheme" :
                      setDesktopTheme(data.getString(key));
                      break;
              }
          }
      }
  
      public static void checkObsoleteOrMissingProperties(JSONObject data) {
          try {
              if (data.has("dxcomponents")) {
                  data.put("wincomponents", data.getString("dxcomponents"));
                  data.remove("dxcomponents");
              }
  
              if (data.has("dxwrapper")) {
                  String dxwrapper = data.getString("dxwrapper");
                  if (dxwrapper.equals("original-wined3d")) {
                      data.put("dxwrapper", DEFAULT_DXWRAPPER);
                  }
                  else if (dxwrapper.startsWith("d8vk-") || dxwrapper.startsWith("dxvk-")) {
                      data.put("dxwrapper", dxwrapper.substring(0, dxwrapper.indexOf("-")));
                  }
              }
  
              if (data.has("graphicsDriver")) {
                  String graphicsDriver = data.getString("graphicsDriver");
                  if (graphicsDriver.equals("turnip-zink")) {
                      data.put("graphicsDriver", "turnip");
                  }
                  else if (graphicsDriver.equals("llvmpipe")) {
                      data.put("graphicsDriver", "virgl");
                  }
              }
  
              if (data.has("envVars") && data.has("extraData")) {
                  JSONObject extraData = data.getJSONObject("extraData");
                  int appVersion = Integer.parseInt(extraData.optString("appVersion", "0"));
                  if (appVersion < 12) {
                      EnvVars defaultEnvVars = new EnvVars(DEFAULT_ENV_VARS);
                      EnvVars envVars = new EnvVars(data.getString("envVars"));
                      for (String name : defaultEnvVars) if (!envVars.has(name)) envVars.put(name, defaultEnvVars.get(name));
                      data.put("envVars", envVars.toString());
                  }
              }
  
              KeyValueSet wincomponents1 = new KeyValueSet(DEFAULT_WINCOMPONENTS);
              KeyValueSet wincomponents2 = new KeyValueSet(data.getString("wincomponents"));
              String result = "";
  
              for (String[] wincomponent1 : wincomponents1) {
                  String value = wincomponent1[1];
  
                  for (String[] wincomponent2 : wincomponents2) {
                      if (wincomponent1[0].equals(wincomponent2[0])) {
                          value = wincomponent2[1];
                          break;
                      }
                  }
  
                  result += (!result.isEmpty() ? "," : "")+wincomponent1[0]+"="+value;
              }
  
              data.put("wincomponents", result);
          }
          catch (JSONException e) {}
      }
  }
  