import { StringCaser } from "@/utils/utils";
import { generateComponentId, getComponentViewBindingId } from "./helpers";
import { generateComponent } from "../translator/TranslatorFragmentXmlAndroid";
import { findComponentsWithNavigationProperty } from "./navigation";

const generateViewHolderName = (fragment) => {
  return `holder_${StringCaser(fragment.props.name, {
    casetype: "lowercase",
    separator: "_",
  })}`;
};

export const generateStaticCarouselDataClass = (fragment, config) => {
  let name = StringCaser(fragment.props.name, { casetype: "capitalize" });
  let apiObj = config.api.find((a) => a.id == fragment.dataSource);
  let api = apiObj ? StringCaser(apiObj.name, { casetype: "camelCase" }) : "";
  const apiField = config.api?.find((apiItem) => {
    return StringCaser(apiItem.name, { casetype: "camelCase" }) === api;
  });
  return `
package com.manaknight.app.data

import androidx.lifecycle.LifecycleOwner
import ${config.packageName}.adapters.${name}CarouselAdapter
import ${config.packageName}.network.Status
import ${config.packageName}.viewmodels.BaasViewModel
import java.io.Serializable



data class ${name}Model(${fragment.props.fields
    .split(",")
    .map((f) => `val ${f}: String`)
    .join(", ")}): Serializable

fun load${name}Data(viewLifecycleOwner: LifecycleOwner, baasViewModel: BaasViewModel, adapter: ${name}CarouselAdapter) {

    baasViewModel.${api}("id,desc", "1,20", "", "").observe(viewLifecycleOwner) {
        when (it.status) {
            Status.ERROR -> println(it.message ?: "Something went wrong")
            Status.LOADING -> {}

            Status.SUCCESS -> {
                val list: List<${name}Model> = it.data?.list!!.map { map ->
                    ${fragment.props.fields
                      .split(",")
                      .map(
                        (f) =>
                          `val ${f} = map["${f.trim()}"]${
                            apiField.columns[f.trim()] == "int"
                              ? `.toString() as? String ?: ""`
                              : `as? String ?: ""`
                          }`
                      )
                      .join("\n ")}
                   
                    ${name}Model( ${fragment.props.fields
    .split(",")
    .map(
      (f) =>
        `${f}${
          apiField.columns[f.trim()] == "int" ? `.substringBefore(".")` : ``
        }`
    )
    .join(", ")})
                }

                adapter.updateData(list)

            }
        }
    }
}



    `;
};

export const generateCarouselAdapter = (carousel, config, fragment) => {
  let name = StringCaser(carousel.props.name, { casetype: "capitalize" });
  let _name = StringCaser(carousel.props.name, {
    casetype: "lowercase",
    separator: "_",
  });

  return `
    package com.manaknight.app.adapters

    import Manaknight.R
    import android.content.Context
    import android.view.LayoutInflater
    import android.view.View
    import android.view.ViewGroup
    import android.widget.TextView
    import android.widget.ImageView
    import ${config.packageName}.data.${name}Model
    import com.manaknight.app.extensions.loadImageFromUrl
    import androidx.navigation.findNavController
    import ${config.packageName}.ui.${StringCaser(fragment.name, {
    casetype: "capitalize",
  })}FragmentDirections
    import androidx.recyclerview.widget.RecyclerView


    
    class ${name}CarouselAdapter(
                              private var dataset: List<${name}Model>
                                ): RecyclerView.Adapter<${name}CarouselAdapter.ViewHolder>()    {
        class ViewHolder(private val view: View): RecyclerView.ViewHolder(view) {
            fun bind(model: ${name}Model) {
                ${carousel.props.fields
                  .split(",")
                  .map((f) => getItemBinding(_name, f))
                  .join("\n ")}

                  ${getActionBinding(carousel, config.fragment)}
            }
        }
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
            val adapterLayout = LayoutInflater.from(parent.context)
                .inflate(R.layout.${generateViewHolderName(
                  carousel
                )}, parent, false)
    
            return ViewHolder(adapterLayout)
        }
    
        override fun getItemCount(): Int {
            return dataset.size;
        }
    
        override fun onBindViewHolder(holder: ViewHolder, position: Int) {
            val item = dataset[position]
            holder.bind(item)
        }

        fun updateData(newData: List<${name}Model>) {
            dataset = newData
            notifyDataSetChanged()
        }
    }
    
    
    `;
};

export const getCarouselViewFields = (fragment) => {
  const content = [];
  const carouselViews = findCarouselViews(fragment, []);
  for (const view of carouselViews) {
    let name = StringCaser(view.props.name, { casetype: "capitalize" });
    content.push(
      ` private lateinit var adapter${name}: ${name}CarouselAdapter`
    );
  }

  return content.join("\n");
};
export const generateCarouselViewFragmentBinding = (
  fragment,
  configuration
) => {
  // This would be generated in the fragment
  const content = [];
  const carouselViews = findCarouselViews(fragment, []);
  for (const view of carouselViews) {
    let name = StringCaser(view.props.name, { casetype: "capitalize" });
    content.push(`

         adapter${name} = ${name}CarouselAdapter(ArrayList())




        val ${getComponentViewBindingId(
          view
        )} = binding.${getComponentViewBindingId(view)}


        ${getComponentViewBindingId(view)}.apply {
            clipChildren = false
            clipToPadding = false
            offscreenPageLimit = 3
            (getChildAt(0) as RecyclerView).overScrollMode =
                RecyclerView.OVER_SCROLL_NEVER
        }




        load${name}Data(viewLifecycleOwner, baasViewModel, adapter${name})
        ${getComponentViewBindingId(view)}.adapter = adapter${name}



        val ${name}CompositePageTransformer = CompositePageTransformer()
        ${name}CompositePageTransformer.addTransformer(MarginPageTransformer((40 * Resources.getSystem().displayMetrics.density).toInt()))
        ${name}CompositePageTransformer.addTransformer { page, position ->
            val r = 1 - abs(position)
            page.scaleY = (0.80f + r * 0.20f)
        }
        ${getComponentViewBindingId(
          view
        )}.setPageTransformer(${name}CompositePageTransformer)
        `);
  }
  return content.join("\n");
};

export const generateCarouselViewImport = (fragment, configuration) => {
  const uniqueLines = new Set();
  const carouselViews = findCarouselViews(fragment, []);
  const content = [];

  for (const view of carouselViews) {
    let name = StringCaser(view.props.name, { casetype: "capitalize" });
    const imports = [
      `${configuration.packageName}.adapters.${name}CarouselAdapter`,
      `${configuration.packageName}.data.load${name}Data`,
      "android.content.res.Resources",
      "androidx.viewpager2.widget.CompositePageTransformer",
      "androidx.viewpager2.widget.MarginPageTransformer",
      "kotlin.math.abs",
      "androidx.recyclerview.widget.RecyclerView",
    ];

    for (const line of imports) {
      if (!uniqueLines.has(line)) {
        uniqueLines.add(line);
        content.push(`import ${line}`);
      }
    }
  }
  return content.join("\n");
};

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

export const buildCarouseloViewHolder = (carouseloView) => {
  let uiTemplate = viewHolderXml(carouseloView);
  let _name = StringCaser(carouseloView.props.name, {
    casetype: "lowercase",
    separator: "_",
  });
  let content = carouseloView.props.fields
    .split(",")
    .map((f) => getItemTemplate(_name, f));

  let action = carouseloView.children.map((f) => getChildrenTemplate(_name, f));

  return uiTemplate
    .replace("{{{CONTENT}}}", content.join("\n"))
    .replace("{{{ACTION}}}", action.join("\n"));
};

const viewHolderXml = (carouselView) => {
  return `<?xml version="1.0" encoding="utf-8"?>
  <androidx.cardview.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:cardCornerRadius="8dp"
    app:cardElevation="4dp"
    app:cardUseCompatPadding="true">

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="16dp">
          {{{CONTENT}}}
          {{{ACTION}}}
    </LinearLayout>

    </androidx.cardview.widget.CardView>

  `;
};

const getChildrenTemplate = (name = "", field = "") => {
  return field ? generateComponent(field) : "";
};

const getItemTemplate = (name = "", field = "") => {
  field = field.trim();

  if (field.indexOf("image") > -1) {
    return `
        <ImageView
            android:id="@+id/${name}_${field}"
            android:layout_width="match_parent"
            android:scaleType="centerCrop"
            android:layout_height="231dp"
            android:layout_margin="2dp"
            android:src="@drawable/ic_loc_active"
             />
        `;
  }

  return `
    <TextView
        android:id="@+id/${name}_${field}"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="${field}"
        android:textSize="12sp"
        android:padding="2dp"
        android:layout_margin="2dp"
        android:textColor="@android:color/black" />
    `;
};

const getItemBinding = (name = "", field = "") => {
  field = field.trim();
  if (field.indexOf("image") > -1) {
    return ` view.findViewById<ImageView>(R.id.${name}_${field}).loadImageFromUrl(model.${field}) `;
  }
  return `view.findViewById<TextView>(R.id.${name}_${field}).text = model.${field}  `;
};

const getActionBinding = (carousel, fragment) => {
  if (findCarouselViews(fragment).length == 0) return "";

  let navElements = findComponentsWithNavigationProperty(carousel);
  const content = [];

  let parentFragment = fragment.find((frag) => frag.id == carousel.pageId);
  const fragmentCapitalizedName = StringCaser(parentFragment.name, {
    casetype: "capitalize",
  });

  for (const element of navElements) {
    if (["sign_up", "login"].includes(element.props.to)) continue;

    let destinationFragment = fragment.find(
      (frag) => frag.id == element.props.to
    );
    const destinationCapitalized = StringCaser(destinationFragment.name, {
      casetype: "capitalize",
    });

    const elementId = generateComponentId(element);
    if (element.name === "ImageView") {
      content.push(` view.findViewById<ImageView>(R.id.${elementId}).setOnClickListener{
        ${
          carousel.props.pass_data
            ? `val action = ${fragmentCapitalizedName}FragmentDirections.action${fragmentCapitalizedName}FragmentTo${destinationCapitalized}Fragment(model)
                    view.findNavController().navigate(action)`
            : `view.findNavController().navigate(R.id.action_${fragmentCapitalizedName}Fragment_to_${destinationCapitalized}Fragment)`
        }
                } `);
    }
    content.push(`view.findViewById<TextView>(R.id.${elementId}).setOnClickListener{
        ${
          carousel.props.pass_data
            ? `val action = ${fragmentCapitalizedName}FragmentDirections.action${fragmentCapitalizedName}FragmentTo${destinationCapitalized}Fragment(model)
                 view.findNavController().navigate(action)`
            : `view.findNavController().navigate(R.id.action_${fragmentCapitalizedName}Fragment_to_${destinationCapitalized}Fragment)`
        }
        
                }  `);
  }

  return content.map((c) => c).join("\n");
};
