# createInstance function

Future<void> createInstance(

1. TextEditingController nameController,
2. TextEditingController locationController,
3. WSLApi api,
4. TextEditingController autoSuggestBox,
5. TextEditingController userController

)

## Implementation

    Future<void> createInstance(
      TextEditingController nameController,
      TextEditingController locationController,
      WSLApi api,
      TextEditingController autoSuggestBox,
      TextEditingController userController,
    ) async {
      plausible.event(name: "wsl_create");
      String label = nameController.text;
      // Replace all special characters with _
      String name = label.replaceAll(RegExp('[^A-Za-z0-9]'), '_');
      if (name != '') {
        String distroName = autoSuggestBox.text;

        // Set paths
        Notify.message('creatinginstance-text'.i18n(), loading: true);
        String location = locationController.text;
        if (location == '') {
          location = prefs.getString("DistroPath") ?? defaultPath;
          location += '/$name';
        }

        // Check if docker image
        bool isDockerImage = false;
        if (distroName.startsWith('dockerhub:')) {
          isDockerImage = true;
          // Remove prefix
          distroName = autoSuggestBox.text.split('dockerhub:')[1];
          // Get tag
          if (!distroName.contains(':')) {
            distroName += ':latest';
          }
          String? image = distroName.split(':')[0];
          String? tag = distroName.split(':')[1];

          if (!distroName.contains('/')) {
            image = 'library/$image';
          }

          bool isDownloaded = false;
          // Check if image already downloaded
          if (await DockerImage().isDownloaded(image, tag: tag)) {
            isDownloaded = true;
          }

          // Check if image exists
          if (!isDownloaded && await DockerImage().hasImage(image, tag: tag)) {
            // Download image
            Notify.message('${'downloading-text'.i18n()}...');
            var docker = DockerImage()..distroName = distroName;
            await docker.getRootfs(name, image, tag: tag,
                progress: (current, total, currentStep, totalStep) {
              if (currentStep != -1) {
                String progressInMB =
                    (currentStep / 1024 / 1024).toStringAsFixed(2);
                // String totalInMB = (total / 1024 / 1024).toStringAsFixed(2);
                String percentage =
                    (currentStep / totalStep * 100).toStringAsFixed(0);
                Notify.message('${'downloading-text'.i18n()}'
                    ' Layer ${current + 1}/$total: $percentage% ($progressInMB MB)');
              } else {
                Notify.message(
                    'extractinglayers-text'.i18n(['$current', '$total']));
              }
            });
            Notify.message('downloaded-text'.i18n());
            // Set distropath with distroName
            distroName = DockerImage().filename(image, tag);
          } else if (!isDownloaded) {
            Notify.message('distronotfound-text'.i18n());
            return;
          }

          if (isDownloaded) {
            // Set distropath with distroName
            distroName = DockerImage().filename(image, tag);
          }
        }

        // Navigator.of(context, rootNavigator: true).pop();

        // Create instance
        ProcessResult result = await api.create(
            name, distroName, location, (String msg) => Notify.message(msg),
            image: isDockerImage);

        // Check if instance was created then handle postprocessing
        if (result.exitCode != 0) {
          Notify.message(WSLApi().utf8Convert(result.stdout));
        } else {
          var userCmds = prefs.getStringList('UserCmds_$distroName');
          var groupCmds = prefs.getStringList('GroupCmds_$distroName');
          if (userCmds != null && groupCmds != null) {
            for (int i = 0; i < groupCmds.length; i++) {
              var cmd = groupCmds[i].replaceAll("/bin/sh -c ", "");
              cmd = cmd.replaceAll(RegExp(r'\s+'), ' ');
              await api.exec(name, [cmd]);
            }
            for (int i = 0; i < userCmds.length; i++) {
              var cmd = userCmds[i].replaceAll("/bin/sh -c ", "");
              // Replace multiple spaces with one
              cmd = cmd.replaceAll(RegExp(r'\s+'), ' ');
              await api.exec(name, [cmd]);
            }
          }
          String user = userController.text;
          if (user != '') {
            List<int> processes = await api.exec(name, [
              'apt-get update',
              'apt-get install -y sudo',
              'useradd -m -s /bin/bash -G sudo $user',
              'passwd $user',
              'echo \'$user ALL=(ALL) NOPASSWD:ALL\' >> /etc/sudoers.d/wslsudo',
              'echo -e \'[user]\ndefault = $user\' > /etc/wsl.conf',
            ]);
            bool success = true;
            for (dynamic process in processes) {
              if (process != 0) {
                success = false;
                break;
              }
            }
            if (success) {
              prefs.setString('StartPath_$name', '/home/$user');
              prefs.setString('StartUser_$name', user);

              Notify.message('createdinstance-text'.i18n());
            } else {
              Notify.message('createdinstancenouser-text'.i18n());
            }
          } else {
            // Install fake systemctl
            if (distroName.contains('Turnkey')) {
              // Set first start variable
              prefs.setBool('TurnkeyFirstStart_$name', true);
              Notify.message('installingfakesystemd-text'.i18n(), loading: true);
              WSLApi().execCmds(
                  name,
                  [
                    'wget https://raw.githubusercontent.com/bostrot/'
                        'fake-systemd/master/systemctl -O /usr/bin/systemctl',
                    'chmod +x /usr/bin/systemctl',
                    '/usr/bin/systemctl',
                  ],
                  onMsg: (output) => null,
                  onDone: () => Notify.message('createdinstance-text'.i18n()));
            } else {
              Notify.message('createdinstance-text'.i18n());
            }
          }
          // Save distro label
          prefs.setString('DistroName_$name', label);
          // Save distro path
          prefs.setString('Path_$name', location);
        }
        // Download distro check
      } else {
        Notify.message('entername-text'.i18n());
      }
    }