package com.autotech.we1l.fragments

import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.GridLayoutManager
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import com.android.volley.VolleyError
import com.autotech.we1l.R
import com.autotech.we1l.activities.MainActivity
import com.autotech.we1l.adapters.*
import com.autotech.we1l.app.User
import com.autotech.we1l.helpers.AnimatorUtils
import com.autotech.we1l.items.BreadCrumb
import com.autotech.we1l.items.Category
import com.autotech.we1l.items.Product
import com.autotech.we1l.my_classes.BaseAdapter
import com.autotech.we1l.my_classes.BaseFragment
import com.autotech.we1l.my_classes.BaseList
import com.autotech.we1l.my_interfaces.IOnBackPressedListener
import com.autotech.we1l.tools.*
import com.autotech.we1l.tools.Language.err_no_internet_connection
import com.autotech.we1l.tools.Language.err_server_connection_error
import com.autotech.we1l.tools.Language.prompt_please_retry
import com.autotech.we1l.tools.Language.toast_added_to_wishlist
import com.autotech.we1l.tools.Language.toast_removed_from_wishlist
import com.autotech.we1l.volley.IVolleyRequest
import com.autotech.we1l.volley.VolleyRequest
import kotlinx.android.synthetic.main.fragment_sub_categories.*
import kotlinx.android.synthetic.main.include_loading_no_data.*
import org.json.JSONObject
import java.lang.Exception

class SubCategoriesFragment : BaseFragment(), IOnBackPressedListener {

    // Adapters:
    private lateinit var categoriesAdapter: SubCategoriesAdapter
    private var productsAdapter: ProductsAdapter? = null
    private lateinit var breadCrumbsAdapter: BreadCrumbsAdapter

    // Vars:
    private val breadCrumbs = BaseList<BreadCrumb>()
    private val allCategories = BaseList<Category>()
    private val categoriesStack = BaseList<Category>()
    private var catId: String = ""
    private val products = BaseList<Product>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        catId = arguments?.getString("CATEGORY_ID")!!
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        rootView = inflater.inflate(R.layout.fragment_sub_categories, container, false)
        return rootView
    }

    override fun setupViews() {

        home.setOnClickListener {
            breadCrumbs.clear()
            breadCrumbsAdapter.clear()
            categoriesStack.clear()
            setupCategories()
        }

        breadCrumbsAdapter = BreadCrumbsAdapter(context!!, breadCrumbs, object : BaseAdapter.OnClickListener<BreadCrumb> {

            override fun onClick(holder: RecyclerView.ViewHolder, position: Int, breadCrumb: BreadCrumb) {
                for (i in position + 1 until breadCrumbs.size) {
                    breadCrumbs.removeAt(i)
                }
                breadCrumbsAdapter.updateData(breadCrumbs)
                for (i in position + 1 until categoriesStack.size) {
                    categoriesStack.removeAt(i)
                }
                setupCategories()
            }
        })

        Tools.setupRVHorizontal(bread_crumb_rv, breadCrumbsAdapter)

        products_text.visibility = if (products.isEmpty()) View.GONE else View.VISIBLE

        productsAdapter = ProductsAdapter(context!!, products, object : BaseAdapter.OnClickListener<Product> {

            override fun onClick(holder: RecyclerView.ViewHolder, position: Int, product: Product) {
                launchProductDetails(context!!, product.id.toString())
            }

            override fun onSpecialClick(view: View, holder: RecyclerView.ViewHolder, position: Int, product: Product) {
                if (product.isInWishList)
                    removeFromWishList(product)
                else
                    addToWishList(product)
            }

        }, false)

        val gridLayoutManager = GridLayoutManager(context, 2)

        Tools.setupRV(products_rv, productsAdapter, gridLayoutManager)
    }

    override fun setupClickListeners() {
        refresh_layout.setOnRefreshListener {
            crucialRequests()
        }
    }

    override fun setupLanguages() {
        super.setupLanguages()
        products_text.text = com.autotech.we1l.app.AppLanguage.getString(Language.attr_products)

        no_data_text.text = com.autotech.we1l.app.AppLanguage.getString(Language.txt_v_no_data)
        loading_text.text = com.autotech.we1l.app.AppLanguage.getString(Language.dialog_loading)
    }

    override fun crucialRequests() {
        if (categoriesStack.isEmpty()) getCategories() else getProducts()
    }

    private fun setupCategories() {

        AnimatorUtils.hideThenShow(full_layout) {
            val currCategories = getCurrCategories()

            if (currCategories.isEmpty()) {
                noData(main_layout)
            } else {
                showData(main_layout)
            }

            categoriesAdapter = SubCategoriesAdapter((activity as AppCompatActivity?)!!, currCategories, object : BaseAdapter.OnClickListener<Category> {
                override fun onClick(holder: RecyclerView.ViewHolder, position: Int, category: Category) {
                    categoriesStack.add(category)
                    breadCrumbs.add(BreadCrumb(category.name!!))
                    breadCrumbsAdapter.updateData(breadCrumbs)
                    setupCategories()
                }
            })

            val gridLayoutManager = GridLayoutManager(context, 2)

            gridLayoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
                override fun getSpanSize(position: Int): Int {
                    return if (currCategories[position].isRectangle) 2 else 1
                }
            }

            Tools.setupRV(categories_rv, categoriesAdapter, gridLayoutManager)

            getProducts()
        }
    }

    private fun getCurrCategories(): BaseList<Category> {
        val currCategories = BaseList<Category>()

        if (categoriesStack.isEmpty()) {
            currCategories.addAll(allCategories)

            allCategories.forEachIndexed { _, category ->
                category.childCategoriesIds.forEachIndexed { _, id ->
                    if (currCategories.findItemById(id) != null)
                        currCategories.remove(currCategories.findItemById(id))
                }
            }
        } else {
            val currCategory = categoriesStack.last()
            currCategory.childCategoriesIds.forEachIndexed { _, id ->
                if (allCategories.findItemById(id) != null) {
                    currCategories.add(allCategories.findItemById(id))
                }
            }
        }
        return currCategories
    }

    override fun onBackPressed(): Boolean {
        return if (categoriesStack.isEmpty()) {
            (activity as MainActivity).setFragment(CategoryFragment(), -1)
            true
        } else {
            categoriesStack.remove(categoriesStack.last())
            breadCrumbs.remove(breadCrumbs.last())
            breadCrumbsAdapter.updateData(breadCrumbs)
            setupCategories()
            true
        }
    }

    private fun getCategories() {
        val inputMap = HashMap<String, String>()
        inputMap[ATTR_SYSTEM_PASSCODE] = SYSTEM_PASSCODE
        inputMap[ATTR_ID] = catId
        inputMap[ATTR_LANGUAGE] = User.getUserLanguageId(context!!)!!.toString()
        inputMap[ATTR_CURRENCY] = (if (User.loadVisibleCurrency(context!!) == null) User.loadCurrency(context!!)!!.id
        else User.loadVisibleCurrency(context!!)!!.id).toString()

        if (User.isValid()) {
            inputMap[ATTR_CUSTOMER] = User.instance!!.id.toString()
        }

        if (!isNetworkAvailable(context!!)) {
            Toast.makeText(context, com.autotech.we1l.app.AppLanguage.getString(err_no_internet_connection), Toast.LENGTH_LONG).show()
            return
        }


        loading(main_layout)

        VolleyRequest.getInstance().post(REQUEST_GET_CATEGORY, inputMap, object : IVolleyRequest {

            override fun onSuccess(response: JSONObject?) {
                if (refresh_layout != null)
                    refresh_layout.isRefreshing = false
                when (response!!.getInt(ATTR_ERROR_CODE)) {
                    CODE_OK -> {

                        try {

                            allCategories.clear()

                            val data = response.getJSONObject(ATTR_DATA).getJSONObject(ATTR_DATA)

                            //for (i in 0 until data.length()) {
                            allCategories.add(Category(data))
                            //}

                            if (allCategories.isEmpty()) {
                                noData(main_layout)
                            } else {
                                showData(main_layout)
                            }
                            setupCategories()

                        } catch (e: Exception) {
                        }
                    }
                }
            }

            override fun onFail(error: VolleyError) {
                if (refresh_layout != null)
                    refresh_layout.isRefreshing = false
                noData(main_layout, com.autotech.we1l.app.AppLanguage.getString(prompt_please_retry))
                Toast.makeText(context, com.autotech.we1l.app.AppLanguage.getString(err_server_connection_error), Toast.LENGTH_LONG).show()

            }
        }).apply { requestsArray.add(this) }
    }

    private fun getProducts() {
        productsAdapter?.clear()

        if (categoriesStack.isEmpty()) {
            products_text.visibility = View.GONE
            return
        }

        if (!isNetworkAvailable(context!!)) {
            Toast.makeText(context, com.autotech.we1l.app.AppLanguage.getString(err_no_internet_connection), Toast.LENGTH_LONG).show()
            return
        }

        loading(main_layout)

        val inputMap = HashMap<String, String>()
        inputMap[ATTR_SYSTEM_PASSCODE] = SYSTEM_PASSCODE
        inputMap[ATTR_ID] = categoriesStack.last().id.toString()
        inputMap[ATTR_CURRENCY] = (if (User.loadVisibleCurrency(context!!) == null) User.loadCurrency(context!!)!!.id
        else User.loadVisibleCurrency(context!!)!!.id).toString()
        inputMap[ATTR_LANGUAGE] = User.getUserLanguageId(context!!)!!.toString()

        if (User.isValid()) {
            inputMap[ATTR_CUSTOMER] = User.instance!!.id.toString()
        }

        VolleyRequest.getInstance().post(REQUEST_GET_CATEGORY, inputMap, object : IVolleyRequest {

            override fun onSuccess(response: JSONObject?) {
                if (refresh_layout != null)
                    refresh_layout.isRefreshing = false
                when (response!!.getInt(ATTR_ERROR_CODE)) {
                    CODE_OK -> {
                        products.clear()
                        val productsJSON = response.getJSONObject(ATTR_DATA)
                                .getJSONObject(ATTR_DATA).getJSONArray(ATTR_PRODUCTS)
                        val categoryId = response.getJSONObject(ATTR_DATA).getJSONObject(ATTR_DATA).getInt(ATTR_ID)
                        for (i in 0 until productsJSON.length()) {
                            products.add(Product(productsJSON.getJSONObject(i), categoryId))
                        }
                        if (products.isEmpty() && getCurrCategories().isEmpty()) {
                            noData(main_layout)
                        } else {
                            showData(main_layout)
                        }
                        if (categoriesStack.isNotEmpty() && categoriesStack.last().id == categoryId) {
                            AnimatorUtils.hideThenShow(products_rv) {
                                products_text.visibility = if (products.isEmpty()) View.GONE else View.VISIBLE

                                productsAdapter!!.updateData(products)
                            }
                        }
                    }
                }
            }

            override fun onFail(error: VolleyError) {
                if (refresh_layout != null)
                    refresh_layout.isRefreshing = false
                noData(main_layout, com.autotech.we1l.app.AppLanguage.getString(prompt_please_retry))
                Toast.makeText(context, com.autotech.we1l.app.AppLanguage.getString(err_server_connection_error), Toast.LENGTH_LONG).show()
            }
        }).apply { requestsArray.add(this) }
    }

    private fun addToWishList(product: Product) {
        val inputMap = HashMap<String, String>()

        inputMap[ATTR_SYSTEM_PASSCODE] = SYSTEM_PASSCODE
        inputMap[ATTR_PRODUCT] = product.id.toString()
        inputMap[ATTR_CUSTOMER] = User.instance!!.id.toString()

        if (!isNetworkAvailable(context!!)) {
            Toast.makeText(context, com.autotech.we1l.app.AppLanguage.getString(err_no_internet_connection), Toast.LENGTH_LONG).show()
            return
        }

        VolleyRequest.getInstance().post(REQUEST_ADD_TO_WISH_LIST, inputMap, object : IVolleyRequest {

            override fun onSuccess(response: JSONObject?) {
                when (response!!.getInt(ATTR_ERROR_CODE)) {
                    CODE_OK -> {
                        activity?.runOnUiThread {
                            product.isInWishList = true
                            productsAdapter?.notifyDataSetChanged()
                            Toast.makeText(context, "${product.name} " + com.autotech.we1l.app.AppLanguage.getString(toast_added_to_wishlist), Toast.LENGTH_LONG).show()
                        }
                    }
                }
            }

            override fun onFail(error: VolleyError) {
                Toast.makeText(context, com.autotech.we1l.app.AppLanguage.getString(err_server_connection_error), Toast.LENGTH_LONG).show()
            }

        }).apply { requestsArray.add(this) }
    }

    private fun removeFromWishList(product: Product) {
        val inputMap = HashMap<String, String>()
        inputMap[ATTR_SYSTEM_PASSCODE] = SYSTEM_PASSCODE
        inputMap[ATTR_CUSTOMER] = User.instance!!.id.toString()
        inputMap[ATTR_PRODUCT] = product.id.toString()

        if (!isNetworkAvailable(context!!)) {
            Toast.makeText(context, com.autotech.we1l.app.AppLanguage.getString(err_no_internet_connection), Toast.LENGTH_LONG).show()
            return
        }

        VolleyRequest.getInstance().post(REQUEST_DELETE_FROM_WISH_LIST, inputMap, object : IVolleyRequest {

            override fun onSuccess(response: JSONObject?) {
                when (response!!.getInt(ATTR_ERROR_CODE)) {
                    CODE_OK -> {
                        product.isInWishList = false
                        productsAdapter?.notifyDataSetChanged()
                        activity?.runOnUiThread {
                            Toast.makeText(context, "${product.name} ${com.autotech.we1l.app.AppLanguage.getString(toast_removed_from_wishlist)}",
                                    Toast.LENGTH_LONG).show()
                        }
                    }
                }
            }

            override fun onFail(error: VolleyError) {
                Toast.makeText(context, com.autotech.we1l.app.AppLanguage.getString(err_server_connection_error), Toast.LENGTH_LONG).show()

            }

        }).apply { requestsArray.add(this) }

    }

    override fun onResume() {
        super.onResume()
        setupCategories()
        breadCrumbsAdapter.updateData(breadCrumbs)
    }
}
