import { StringCaser } from "@/utils/utils";
import { getType, getDefinitionType } from "../utils/helpers";

export default (configuration, viewModel) => {
  //TODO: make the view model functions
  return `
package ${configuration.packageName}.viewmodels

import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.liveData
import ${configuration.packageName}.extensions.Constants
import ${configuration.packageName}.model.remote.*
import ${configuration.packageName}.network.Resource
import ${configuration.packageName}.repositories.APIRepository
import com.google.gson.Gson
import kotlinx.coroutines.Dispatchers

class ${viewModel.nameUpperCase}ViewModel(
    private val repository: APIRepository
) : ViewModel() {

    fun applyPeek(lat:Double,lng: Double,deviceId: Int): LiveData<Resource<ApplyPeekResponse>> {
        return repository.applyPeek(CaptureDealRequest(deviceId, "($lat,$lng)", null))
    }

    fun buyingPeek(): LiveData<Resource<BuyingPeekResponse>> {
        return repository.buyingPeek()
    }
}
  `;
};

/*
  fun updateProfileSettings(
        language_type: Int, skill_levels: Int, voice_speeds: Int
    ): LiveData<Resource<UpdateProfileResponse>> {
        return repository.updateProfileSettings(
            UpdateProfileRequest(
                language_type, skill_levels, voice_speeds
            )
        )
    }


    fun getBooks(): LiveData<Resource<BookResponse>> {
          return repository.getBooks()
      }

*/

export function findComponents(data, name, result = []) {
  if (!Array.isArray(data)) data = [data];
  for (const item of data) {
    if ("components" in item) {
      findComponents(item.components, name, result);
    }
    if ("children" in item) {
      findComponents(item.children, name, result);
    }
    if (item.name === name) {
      result.push(item);
    }
  }
  return result;
}

export const MapBaasViewModel = (configuration) => {
  const chatBotComp = (configuration) => {
    const result = findComponents(configuration.fragment, "ChatBotUi")
    if (!findComponents(configuration.fragment, "ChatBotUi")) {
      return " ";
    }
    else {
      return `
      fun sendMessageToBot(request: String): LiveData<Resource<ChatBotTextResponse>> {
        return repository.sendMessageToBot(request)
    }

    fun sendMessageToBot(request: ChatBotRequest): LiveData<Resource<ChatBotTextResponse>> {
        return repository.sendMessageToBot(request)
    }
      `
    }
  }

  const chatComp = (configuration) => {
    const result = findComponents(configuration.fragment, "ChatUi")
    if (!findComponents(configuration.fragment, "ChatUi")) {
      return " ";
    }
    else {
      return `
      fun getAllUser(): LiveData<Resource<FriendListResponse>> {
        return repository.getAllUser()
    }
  
    fun createRoomRequests(user_id: Int, other_user_id: Int?): LiveData<Resource<CreateRoomResponse>> {
      return repository.createRoomRequests(CreateRoomRequests(user_id, other_user_id))
  }
  
      fun sendTextMessage(room_id: String, user_id: Int, message: String?): LiveData<Resource<ChatTextResponse>> {
        return repository.sendTextMessage(ChatTextRequest(room_id, user_id, message))
    }
  
    fun getChats(room_id: String): LiveData<Resource<ChatResponse>> {
        return repository.getChats(ChatRequest(room_id))
    }
  
    fun getStartPool(user_id: Int): LiveData<Resource<SingleChatMessageResponse>> {
        return repository.getStartPool(user_id)
    }
  
    fun getAllRoom(user_id: Int): LiveData<Resource<ChatRoomResponse>> {
        return repository.getAllRoom(user_id)
    }
      
      `

    }
  }


  return `
  package com.manaknight.app.viewmodels

  import androidx.lifecycle.LiveData
  import androidx.lifecycle.ViewModel
  import ${configuration.packageName}.model.remote.*
  import ${configuration.packageName}.network.Resource
  import ${configuration.packageName}.repositories.APIRepository
  import okhttp3.MultipartBody
  
  class BaasViewModel(
      private val repository: APIRepository
  ) : ViewModel() {

      ${chatComp(configuration)}
      ${chatBotComp(configuration)}
      ${buildActions(configuration.api)}
  
  }
  `;
};

const buildActions = (apis) => {
  let endpoints = [];
  apis.map((api) => {
    endpoints.push(`
    fun ${StringCaser(api.name, {
      casetype: "camelCase",
    })}(${spreadRepositoryArgs(api)}): LiveData<Resource<${getResponseName(api)}>> {
       return repository.${StringCaser(api.name, {
      casetype: "camelCase",
    })}(${buildRepositoryArgs(api)})
     }

   `);
  });
  return endpoints.join("\n");
};

const getResponseName = (api) => {
  const modelName = StringCaser(api.name, { casetype: "PascalCase" });
  return `${modelName}Response`;
};

const spreadRepositoryArgs = (api) => {
  let params = [];
  let body = api.inputs
    .filter((input) => input.type == "body")
    .map(
      (input) =>
        `${StringCaser(input.name, {
          casetype: "camelCase",
        })}: ${getDefinitionType(input.dataType)}`
    )
    .join(",");
  if (body.trim().length > 0) params.push(body);
  let path = api.inputs
    .filter((input) => input.type == "path")
    .map(
      (input) =>
        `${StringCaser(input.name, {
          casetype: "camelCase",
        })}: ${getDefinitionType(input.dataType)}`
    )
    .join(",");
  if (path.trim().length > 0) params.push(path);
  let query = api.inputs
    .filter((input) => input.type == "query")
    .map(
      (input) =>
        `${StringCaser(input.name, {
          casetype: "camelCase",
        })}: ${getDefinitionType(input.dataType)}`
    )
    .join(",");
  if (query.trim().length > 0) params.push(query);
  let multipart = api.inputs
    .filter((input) => input.type == "multipart")
    .map(
      (input) =>
        `${StringCaser(input.name, {
          casetype: "camelCase",
        })}: MultipartBody.Part`
    )
    .join(",");
  if (multipart.trim().length > 0) params.push(multipart);

  return `${params.join(",")}`;
};
const buildRepositoryArgs = (api) => {
  const request = buildRequest(
    api.inputs.filter((input) => input.type == "body"),
    api
  );
  let path = api.inputs
    .filter((input) => input.type == "path")
    .map((input) => `${StringCaser(input.name, { casetype: "camelCase" })}`)
    .map(
      (query, index, array) =>
        ` ${query}${index === array.length - 1 ? "," : ""}`
    )
    .join(",");
  let query = api.inputs
    .filter((input) => input.type == "query")
    .map((input) => `${StringCaser(input.name, { casetype: "camelCase" })}`)
    .map(
      (query, index, array) =>
        ` ${query}${index === array.length - 1 ? "," : ""}`
    )
    .join(",");
  let multipart = api.inputs
    .filter((input) => input.type == "multipart")
    .map((input) => `${StringCaser(input.name, { casetype: "camelCase" })}`)
    .map(
      (query, index, array) =>
        ` ${query}${index === array.length - 1 ? "," : ""}`
    )
    .join(",");

  return `  ${request} ${path} ${query} ${multipart} `;
};

const buildRequest = (inputs, api) => {
  if (inputs.length === 0) return ``;
  const modelName =
    StringCaser(api.name, { casetype: "PascalCase" }) + "Request";
  const params = inputs
    .map((input) => `${StringCaser(input.name, { casetype: "camelCase" })}`)
    .join(",");
  return `${modelName}(${params}),`;
};
