import JSZip from "jszip";
import { saveAs } from "file-saver";
import SettingGradle from "./flatfile/SettingGradle";
import Gradlewbat from "./flatfile/Gradlewbat";
import GradleProperties from "./flatfile/GradleProperties";
import BuildGradle from "./flatfile/BuildGradle";
import BuildGradleApp from "./flatfile/BuildGradleApp";
import GitIgnoreAndroid from "./flatfile/GitIgnoreAndroid";
import GitIgnoreAndroidApp from "./flatfile/GitIgnoreAndroidApp";
import ProguardRulesPro from "./flatfile/ProguardRulesPro";
import TranslatorManifestAndroid from "./translator/TranslatorManifestAndroid";
import AttrsColors from "./flatfile/AttrsColors";
import AttrsDimens from "./flatfile/AttrsDimens";
import AttrsStrings from "./flatfile/AttrsStrings";
import AttrsMenuDrawer from "./flatfile/AttrsMenuDrawer";
import TranslatorAppAndroid from "./translator/TranslatorAppAndroid";
import TranslatorMainActivityAndroid from "./translator/TranslatorMainActivityAndroid";
import TranslatorLocalAppPreferenceAndroid from "./translator/TranslatorLocalAppPreferenceAndroid";
import TranslatorRemoteDataSourceAndroid from "./translator/TranslatorRemoteDataSourceAndroid";
import TranslatorModulesAndroid from "./translator/TranslatorModulesAndroid";
import TranslatorApiServiceAndroid from "./translator/TranslatorApiServiceAndroid";
import ExtensionCommonAndroid from "./flatfile/ExtensionCommonAndroid";
import TranslatorConstantAndroid from "./translator/TranslatorConstantAndroid";
import TranslatorEnumAndroid from "./translator/TranslatorEnumAndroid";
import FragmentDelegate from "./flatfile/FragmentDelegate";
import StringExtensionAndroid from "./flatfile/StringExtensionAndroid";
import ExtensionViewAndroid from "./flatfile/ExtensionViewAndroid";
import MyFirebasePushNotifications from "./flatfile/MyFirebasePushNotifications";
import TranslatorRepositoryAndroid from "./translator/TranslatorRepositoryAndroid";
import TranslatorFragmentAndroid from "./translator/TranslatorFragmentAndroid";
import MappingViewModelAndroid, {
  MapBaasViewModel,
} from "./mapping/MappingViewModelAndroid";
import TranslatorActivityAndroid from "./translator/TranslatorActivityAndroid";
import {
  mapRequestModels,
  mapResponseModels,
} from "./mapping/MappingModelAndroid";
import TranslatorMainActivityXml from "./translator/TranslatorMainActivityXml";
import {
  BenPascalCase,
  StringCaser,
} from "@/components/WebExportReact/src/utils/helpers";
import TranslatorFragmentXmlAndroid from "./translator/TranslatorFragmentXmlAndroid";
import { gitIgnore } from "@/components/WebExportReact/src/utils/template";
import AttrsValue from "./flatfile/AttrsValue";
import TranslatorFragmentNavigations from "./translator/TranslatorFragmentNavigations";
import AttrsThemes from "./flatfile/AttrsThemes";
import AttrsDataExtractionRules from "./flatfile/AttrsDataExtractionRules";
import AttrsBackupRules from "./flatfile/AttrsBackupRules";
import AttrsFileProvider from "./flatfile/AttrsFileProvider";
import generateStaticImages from "./flatfile/generateStaticImages";
import generateDefaultAnim from "./flatfile/generateDefaultAnim";
import generateDefaultFonts from "./flatfile/generateDefaultFonts";
import GoogleServicesKey from "./flatfile/GoogleServicesKey";
import RetrofitApiClient from "./flatfile/RetrofitApiClient";
import ResourceAndroid from "./flatfile/ResourceAndroid";
import BaseDataSource from "./flatfile/BaseDataSource";
import MessageResponse from "./flatfile/MessageResponse";
import AnimalModel from "./flatfile/AnimalModel";
import ChatMessage from "./model/ChatMessage";
import FileUtils from "./flatfile/FileUtils";
import { generateAuthUI } from "./auth/auth";
import { generateAlertUI } from "./alerts/alerts";
import { JwtUtil } from "./flatfile/JwtUtil";
import { generateBillingUI } from "./billing/billing";
import { searchXML } from "./utils/search";
import { Security } from "./flatfile/Security";
import { generateOtherUI } from "./OtherUI/otherUi";
import SimpleChatUtil from "./androidUtils/SimpleChatUtil";
import SimpleChatView from "./widget/SimpleChatView";

/**
 * @typedef {function(any, any): void} CallbackFunction
 */

/**
 * @param {*} configuration - The project configuration
 * @param {"zip" | "copyList"} exportType - The export type
 * @param {CallbackFunction} [cb=null] - The callback function
 */

const AndroidBuilder = async (configuration, exportType, cb = null) => {
  console.log("configuration");
  /**
   * Steps:
   * - Build package name
   * - Build folders
   * - Build android manifest file
   * - Build SharedPreference file
   * - Build MainActivity
   * - Pull down all apis, make viewmodels
   * - Make activities
   * - Make fragments
   * - Make gradle
   */

  try {
    if (!configuration) {
      throw new Error(
        "Invalid Project configuration, please pass a valid project configuration data"
      );
    }

    if (!["zip", "copyList"].includes(exportType)) {
      throw new Error(
        "Invalid Export Type, the export type must be 'zip | copyList'"
      );
    }
    const zip = new JSZip();
    const fileName = `baas_android_${configuration.name}.zip`;
    let copyList = [];
    let generated_files = [];

    zip.folder("app");
    zip.folder("app/src");
    zip.folder("app/src/main");
    zip.folder("app/src/main/res");
    zip.folder("app/src/main/res/anim");
    zip.folder("app/src/main/res/drawable");
    zip.folder("app/src/main/res/mipmap-hdpi");
    zip.folder("app/src/main/res/mipmap-mdpi");
    zip.folder("app/src/main/res/mipmap-xhdpi");
    zip.folder("app/src/main/res/mipmap-xxhdpi");
    zip.folder("app/src/main/res/mipmap-xxxhdpi");
    zip.folder("app/src/main/res/layout");
    zip.folder("app/src/main/res/menu");
    zip.folder("app/src/main/res/font");
    zip.folder("app/src/main/res/raw");
    zip.folder("app/src/main/res/values");
    zip.folder("app/src/main/java");
    zip.folder("app/src/main/java/com");

    zip.folder("app/src/main/java/com/" + configuration.name.toLowerCase());
    zip.folder(
      "app/src/main/java/com/" + configuration.name.toLowerCase() + "/app"
    );
    zip.folder(
      "app/src/main/java/com/" +
        configuration.name.toLowerCase() +
        "/app/adapters"
    );
    zip.folder(
      "app/src/main/java/com/" + configuration.name.toLowerCase() + "/app/data"
    );
    zip.folder(
      "app/src/main/java/com/" +
        configuration.name.toLowerCase() +
        "/app/data/local"
    );
    zip.folder(
      "app/src/main/java/com/" +
        configuration.name.toLowerCase() +
        "/app/data/remote"
    );
    zip.folder(
      "app/src/main/java/com/" + configuration.name.toLowerCase() + "/app/di"
    );
    zip.folder(
      "app/src/main/java/com/" +
        configuration.name.toLowerCase() +
        "/app/extensions"
    );
    zip.folder(
      "app/src/main/java/com/" + configuration.name.toLowerCase() + "/app/utils"
    );
    zip.folder(
      "app/src/main/java/com/" + configuration.name.toLowerCase() + "/app/fcm"
    );
    zip.folder(
      "app/src/main/java/com/" + configuration.name.toLowerCase() + "/app/model"
    );
    zip.folder(
      "app/src/main/java/com/" +
        configuration.name.toLowerCase() +
        "/app/model/remote"
    );
    zip.folder(
      "app/src/main/java/com/" +
        configuration.name.toLowerCase() +
        "/app/network"
    );
    zip.folder(
      "app/src/main/java/com/" +
        configuration.name.toLowerCase() +
        "/app/repositories"
    );
    zip.folder(
      "app/src/main/java/com/" +
        configuration.name.toLowerCase() +
        "/app/service"
    );
    zip.folder(
      "app/src/main/java/com/" + configuration.name.toLowerCase() + "/app/ui"
    );
    zip.folder(
      "app/src/main/java/com/" +
        configuration.name.toLowerCase() +
        "/app/viewmodels"
    );

    //initialize copy list
    copyList.push({ fileName: ".gitignore", content: gitIgnore() });
    copyList.push({
      fileName: "settings.gradle",
      content: SettingGradle(configuration.projectId),
    });
    copyList.push({
      fileName: "gradlew.bat",
      content: Gradlewbat(configuration),
    });
    copyList.push({
      fileName: "gradle.properties",
      content: GradleProperties(configuration),
    });
    // copyList.push({
    //   fileName: "local.properties",
    //   content: "",
    // });
    copyList.push({
      fileName: "build.gradle",
      content: BuildGradle(configuration),
    });
    copyList.push({
      fileName: ".gitignore",
      content: GitIgnoreAndroid(configuration),
    });
    // copyList.push({
    //   fileName: "build.gradle",
    //   content: GitIgnoreAndroidApp(configuration),
    // });
    copyList.push({
      fileName: "app/proguard-rules.pro",
      content: ProguardRulesPro(configuration),
    });
    copyList.push({
      fileName: "app/build.gradle",
      content: BuildGradleApp(
        configuration.name,
        configuration.baseUrl,
        btoa(`${configuration.projectId}:${configuration.secret}`)
      ),
    });
    copyList.push({
      fileName: "app/google-services.json",
      content: GoogleServicesKey(),
    });
    copyList.push({
      fileName: `app/src/main/AndroidManifest.xml`,
      content: TranslatorManifestAndroid(configuration),
    });
    copyList.push({
      fileName:
        "app/src/main/java/com/" +
        configuration.name.toLowerCase() +
        "/app/App.kt",
      content: TranslatorAppAndroid(configuration),
    });

    copyList.push({
      fileName:
        "app/src/main/java/com/" +
        configuration.name.toLowerCase() +
        "/app/MainActivity.kt",
      content: TranslatorMainActivityAndroid(configuration),
    });

    //data values
    copyList.push({
      fileName:
        "app/src/main/java/com/" +
        configuration.name.toLowerCase() +
        "/app/data/local/AppPreferences.kt",
      content: TranslatorLocalAppPreferenceAndroid(configuration),
    });

    //utils
    copyList.push({
      fileName:
        "app/src/main/java/com/" +
        configuration.name.toLowerCase() +
        "/app/utils/FileUtils.kt",
      content: FileUtils(configuration),
    });

    copyList.push({
      fileName:
        "app/src/main/java/com/" +
        configuration.name.toLowerCase() +
        "/app/utils/JwtUtil.kt",
      content: JwtUtil(configuration),
    });

    copyList.push({
      fileName:
        "app/src/main/java/com/" +
        configuration.name.toLowerCase() +
        "/app/utils/Security.kt",
      content: Security(configuration),
    });
    copyList.push({
      fileName:
        "app/src/main/java/com/" +
        configuration.name.toLowerCase() +
        "/app/utils/SimpleChatUtil.kt",
      content: SimpleChatUtil(configuration),
    });

    //auth
    copyList = copyList.concat(generateAuthUI(configuration));
    //payment
    copyList = copyList.concat(generateBillingUI(configuration));
    //alerts
    copyList = copyList.concat(generateAlertUI(configuration));
    // other prebuilt UI
    copyList = copyList.concat(generateOtherUI(configuration));

    //search
    if (
      configuration?.appBar?.some((bar) =>
        bar?.selectedActions?.includes("Search")
      )
    ) {
      copyList.push({
        fileName: "app/src/main/res/menu/search_menu.xml",
        content: searchXML(configuration),
      });
    }

    // //Cart
    if (
      configuration?.appBar?.some((bar) =>
        bar?.selectedActions?.includes("Cart")
      )
    ) {
      copyList.push({
        fileName: "app/src/main/res/menu/cart_menu.xml",
        content: `<menu xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">


        <item
            android:id="@+id/actionCart"
            android:icon="@drawable/ic_cart"
            android:title="Cart"
            app:showAsAction="ifRoom|collapseActionView" />

    </menu>`,
      });
    }

    //di folder
    copyList.push({
      fileName:
        "app/src/main/java/com/" +
        configuration.name.toLowerCase() +
        "/app/di/Modules.kt",
      content: TranslatorModulesAndroid(configuration),
    });

    //network folder
    copyList.push({
      fileName:
        "app/src/main/java/com/" +
        configuration.name.toLowerCase() +
        "/app/network/ApiService.kt",
      content: TranslatorApiServiceAndroid(configuration),
    });

    copyList.push({
      fileName:
        "app/src/main/java/com/" +
        configuration.name.toLowerCase() +
        "/app/network/BaseDataSource.kt",
      content: BaseDataSource(configuration),
    });

    copyList.push({
      fileName:
        "app/src/main/java/com/" +
        configuration.name.toLowerCase() +
        "/app/network/RemoteDataSource.kt",
      content: TranslatorRemoteDataSourceAndroid(configuration),
    });

    copyList.push({
      fileName:
        "app/src/main/java/com/" +
        configuration.name.toLowerCase() +
        "/app/network/Resource.kt",
      content: ResourceAndroid(configuration),
    });

    copyList.push({
      fileName:
        "app/src/main/java/com/" +
        configuration.name.toLowerCase() +
        "/app/network/RetrofitApiClient.kt",
      content: RetrofitApiClient(configuration),
    });

    //extensions values
    copyList.push({
      fileName:
        "app/src/main/java/com/" +
        configuration.name.toLowerCase() +
        "/app/extensions/Common.kt",
      content: ExtensionCommonAndroid(configuration),
    });

    copyList.push({
      fileName:
        "app/src/main/java/com/" +
        configuration.name.toLowerCase() +
        "/app/extensions/Constants.kt",
      content: TranslatorConstantAndroid(configuration),
    });

    copyList.push({
      fileName:
        "app/src/main/java/com/" +
        configuration.name.toLowerCase() +
        "/app/extensions/Enums.kt",
      content: TranslatorEnumAndroid(configuration),
    });

    copyList.push({
      fileName:
        "app/src/main/java/com/" +
        configuration.name.toLowerCase() +
        "/app/extensions/FragmentDelegate.kt",
      content: FragmentDelegate(configuration),
    });

    copyList.push({
      fileName:
        "app/src/main/java/com/" +
        configuration.name.toLowerCase() +
        "/app/extensions/StringExtensions.kt",
      content: StringExtensionAndroid(configuration),
    });

    copyList.push({
      fileName:
        "app/src/main/java/com/" +
        configuration.name.toLowerCase() +
        "/app/extensions/View.kt",
      content: ExtensionViewAndroid(configuration),
    });

    //fcm values
    copyList.push({
      fileName:
        "app/src/main/java/com/" +
        configuration.name.toLowerCase() +
        "/app/fcm/MyFirebasePushNotifications.kt",
      content: MyFirebasePushNotifications(configuration),
    });

    //adapter values
    //TODO

    //repository values
    //TODO
    copyList.push({
      fileName:
        "app/src/main/java/com/" +
        configuration.name.toLowerCase() +
        "/app/repositories/APIRepository.kt",
      content: TranslatorRepositoryAndroid(configuration),
    });

    //model values - Hold for now

    copyList.push({
      fileName:
        "app/src/main/java/com/" +
        configuration.name.toLowerCase() +
        "/app/model/remote/" +
        "MessageResponse.kt",
      content: MessageResponse(configuration),
    });

    copyList.push({
      fileName:
        "app/src/main/java/com/" +
        configuration.name.toLowerCase() +
        "/app/model/remote/" +
        "AnimalModel.kt",
      content: AnimalModel(configuration),
    });

    for (let i = 0; i < configuration.api.length; i++) {
      const singleModel = configuration.api[i];
      if (!singleModel) continue;
      // request
      const singleModelObjectResult = mapRequestModels(
        configuration,
        singleModel
      );
      if (typeof singleModelObjectResult !== "undefined") {
        // if we don't have inputs then we don't need the request models
        copyList.push({
          fileName:
            "app/src/main/java/com/" +
            configuration.name.toLowerCase() +
            "/app/model/remote/" +
            singleModelObjectResult.fileName,
          content: singleModelObjectResult.content,
        });
      }

      // response
      const singleResponseObjectResult = mapResponseModels(
        configuration,
        singleModel
      );
      copyList.push({
        fileName:
          "app/src/main/java/com/" +
          configuration.name.toLowerCase() +
          "/app/model/remote/" +
          singleResponseObjectResult.fileName,
        content: singleResponseObjectResult.content,
      });
    }

    //viewmodel values
    copyList.push({
      fileName:
        "app/src/main/java/com/" +
        configuration.name.toLowerCase() +
        "/app/viewmodels/" +
        "BaasViewModel.kt",
      content: MapBaasViewModel(configuration),
    });
    //TODO
    // for (let i = 0; i < configuration.api.length; i++) {
    //   const singleModel = configuration.api[i];
    //   if (!singleModel) continue
    //   const singleModelObjectResult = MappingViewModelAndroid(
    //     configuration,
    //     singleModel //TODO process this
    //   );
    //   // "/app/viewmodels/" +
    //   // for now don't create view Models
    //   copyList.push({
    //     fileName:
    //       "app/src/main/java/com/" +
    //       configuration.name.toLowerCase() +
    //       "/app/viewmodels/" +
    //       singleModelObjectResult.fileName,
    //     content: singleModelObjectResult.content,
    //   });
    // }
    // Main Activity values
    copyList.push({
      fileName: `app/src/main/java/com/${configuration.name.toLowerCase()}/app/MainActivity.kt`,
      content: TranslatorMainActivityAndroid(configuration),
    });

    copyList = copyList.concat(
      TranslatorMainActivityXml(configuration, configuration.activity)
    );

    //fragment values
    //TODO
    for (const element of configuration.fragment) {
      const singleFragment = element;
      const singleFragmentContent = TranslatorFragmentAndroid(
        configuration,
        singleFragment //TODO process this
      );
      // console.log(singleFragmentContent);
      copyList.push({
        fileName: `app/src/main/java/com/${configuration.name.toLowerCase()}/app/ui/fragments/${singleFragment.name.toLowerCase()}/${BenPascalCase(
          singleFragment.name
        )}Fragment.kt`,
        content: singleFragmentContent,
      });
    }

    copyList = copyList.concat(
      TranslatorFragmentXmlAndroid(
        configuration,
        configuration.fragment //TODO process this
      )
    );
    //anim
    copyList = copyList.concat(await generateDefaultAnim());
    // drawable & minmap(s)
    copyList = copyList.concat(await generateStaticImages());
    // font
    copyList = copyList.concat(await generateDefaultFonts());

    copyList.push({
      fileName: `app/src/main/res/navigation/mobile_navigation.xml`,
      content: TranslatorFragmentNavigations(
        configuration.fragment,
        configuration
      ),
    });

    //activity values
    //TODO
    // for (let i = 0; i < configuration.activity.length; i++) {
    //   const singleActivity = activity[i];
    //   const singleActivityObjectResult = TranslatorActivityAndroid(
    //     configuration,
    //     singleActivity //TODO process this
    //   );
    //   copyList.push({
    //     fileName:
    //       "app/src/main/java/com/" +
    //       configuration.name.toLowerCase() +
    //       "/app/" +
    //       singleActivityObjectResult.fileName,
    //     content: singleActivityObjectResult.content,
    //   });
    // }

    //menu values
    //TODO

    //res values
    copyList.push({
      fileName: "app/src/main/res/values/attrs.xml",
      content: AttrsValue(configuration),
    });

    copyList.push({
      fileName: "app/src/main/res/values/colors.xml",
      content: AttrsColors(configuration),
    });

    copyList.push({
      fileName: "app/src/main/res/values/dimens.xml",
      content: AttrsDimens(configuration),
    });

    copyList.push({
      fileName: "app/src/main/res/values/strings.xml",
      content: AttrsStrings(configuration.name, configuration.fragment),
    });
    copyList.push({
      fileName: "app/src/main/res/values/themes.xml",
      content: AttrsThemes(configuration.name, configuration.fragment),
    });
    copyList.push({
      fileName: "app/src/main/res/xml/data_extraction_rules.xml",
      content: AttrsDataExtractionRules(
        configuration.name,
        configuration.fragment
      ),
    });
    copyList.push({
      fileName: "app/src/main/res/xml/backup_rules.xml",
      content: AttrsBackupRules(configuration.name, configuration.fragment),
    });
    copyList.push({
      fileName: "app/src/main/res/xml/file_provider.xml",
      content: AttrsFileProvider(configuration.name, configuration.fragment),
    });

    copyList.push({
      fileName: `app/src/main/res/menu/${
        configuration.nav !== "bottomBar"
          ? "navigation_menu"
          : "bottom_nav_menu"
      }.xml`,
      content: AttrsMenuDrawer(configuration.name, configuration.menu),
    });

    //copy list into zip
    copyList.forEach((singleCopy) => {
      zip.file(singleCopy.fileName, singleCopy.content);
    });

    if (exportType === "zip") {
      zip.generateAsync({ type: "blob" }).then(function (content) {
        saveAs(content, fileName);
      });
      if (cb) {
        cb(null, "Zip Exported");
      }
    } else if (exportType === "copyList") {
      if (cb) {
        cb(null, copyList);
      } else {
        return copyList;
      }
    }
  } catch (e) {
    console.log("Builder Error: ", e);
    if (cb) {
      cb(e.message, null);
    }
    return { error: e.message };
  }
};
export default AndroidBuilder;
