/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.spark.sql.execution.datasources

import java.util
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.atomic.AtomicLong

import scala.collection.JavaConverters._
import scala.collection.mutable

import org.apache.commons.lang3.StringUtils
import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.fs.{FileStatus, Path}
import org.apache.hadoop.io.NullWritable
import org.apache.hadoop.mapreduce.{Job, JobContext, TaskAttemptContext}
import org.apache.spark.internal.Logging
import org.apache.spark.internal.io.FileCommitProtocol
import org.apache.spark.internal.io.FileCommitProtocol.TaskCommitMessage
import org.apache.spark.sql.{CarbonEnv, Row, SparkSession}
import org.apache.spark.sql.catalyst.{InternalRow, TableIdentifier}
import org.apache.spark.sql.catalyst.catalog.ExternalCatalogUtils
import org.apache.spark.sql.internal.SQLConf
import org.apache.spark.sql.sources.DataSourceRegister
import org.apache.spark.sql.types._
import org.apache.spark.TaskContext

import org.apache.carbondata.common.Maps
import org.apache.carbondata.core.constants.{CarbonCommonConstants, CarbonLoadOptionConstants}
import org.apache.carbondata.core.datastore.compression.CompressorFactory
import org.apache.carbondata.core.datastore.impl.FileFactory
import org.apache.carbondata.core.indexstore
import org.apache.carbondata.core.metadata.datatype.DataTypes
import org.apache.carbondata.core.statusmanager.{LoadMetadataDetails, SegmentStatusManager}
import org.apache.carbondata.core.util.{CarbonProperties, DataLoadMetrics, DataTypeConverter, DataTypeConverterImpl, DataTypeUtil, ObjectSerializationUtil, ThreadLocalSessionInfo}
import org.apache.carbondata.core.util.path.CarbonTablePath
import org.apache.carbondata.hadoop.api.{CarbonOutputCommitter, CarbonTableOutputFormat}
import org.apache.carbondata.hadoop.api.CarbonTableOutputFormat.CarbonRecordWriter
import org.apache.carbondata.hadoop.internal.ObjectArrayWritable
import org.apache.carbondata.processing.loading.constants.DataLoadProcessorConstants
import org.apache.carbondata.processing.loading.model.{CarbonLoadModel, CarbonLoadModelBuilder, LoadOption}
import org.apache.carbondata.processing.util.CarbonBadRecordUtil
import org.apache.carbondata.spark.util.{CarbonScalaUtil, CommonUtil}

class SparkCarbonTableFormat
  extends FileFormat
    with DataSourceRegister
    with Logging
with Serializable {

  override def shortName(): String = "carbondata"

  override def inferSchema(sparkSession: SparkSession,
      options: Map[String, String],
      files: Seq[FileStatus]): Option[StructType] = {
    None
  }

  override def prepareWrite(
      sparkSession: SparkSession,
      job: Job,
      options: Map[String, String],
      dataSchema: StructType): OutputWriterFactory = {
    val conf = job.getConfiguration
    conf.setClass(
      SQLConf.OUTPUT_COMMITTER_CLASS.key,
      classOf[CarbonOutputCommitter],
      classOf[CarbonOutputCommitter])
    conf.set("carbondata.commit.protocol", "carbondata.commit.protocol")
    conf.set("mapreduce.task.deleteTaskAttemptPath", "false")
    conf.set("mapreduce.fileoutputcommitter.marksuccessfuljobs", "false")
    conf.set("mapreduce.fileoutputcommitter.algorithm.version", "2")
    job.setOutputFormatClass(classOf[CarbonTableOutputFormat])
    val table = CarbonEnv.getCarbonTable(
      TableIdentifier(options("tableName"), options.get("dbName")))(sparkSession)
    val model = new CarbonLoadModel
    val columnCompressor = table.getTableInfo.getFactTable.getTableProperties.asScala
      .getOrElse(CarbonCommonConstants.COMPRESSOR,
        CompressorFactory.getInstance().getCompressor.getName)
    model.setColumnCompressor(columnCompressor)
    model.setMetrics(new DataLoadMetrics())

    val carbonProperty = CarbonProperties.getInstance()
    val optionsFinal = LoadOption.fillOptionWithDefaultValue(options.asJava)
    val tableProperties = table.getTableInfo.getFactTable.getTableProperties
    optionsFinal.put("sort_scope", tableProperties.asScala.getOrElse("sort_scope",
      carbonProperty.getProperty(CarbonLoadOptionConstants.CARBON_OPTIONS_SORT_SCOPE,
        carbonProperty.getProperty(CarbonCommonConstants.LOAD_SORT_SCOPE,
          CarbonCommonConstants.LOAD_SORT_SCOPE_DEFAULT))))
    // If spatial index property is configured, set flag to indicate spatial columns are present.
    // So that InputProcessorStepWithNoConverterImpl can generate the values for those columns,
    // convert them and then apply sort/write steps.
    val spatialIndex =
    table.getTableInfo.getFactTable.getTableProperties.get(CarbonCommonConstants.SPATIAL_INDEX)
    if (spatialIndex != null) {
      val sortScope = optionsFinal.get("sort_scope")
      if (sortScope.equalsIgnoreCase(CarbonCommonConstants.LOAD_SORT_SCOPE_DEFAULT)) {
        // Spatial Index non-schema column must be sorted
        optionsFinal.put("sort_scope", "LOCAL_SORT")
      }
      model.setNonSchemaColumnsPresent(true)
    }
    optionsFinal
      .put("bad_record_path", CarbonBadRecordUtil.getBadRecordsPath(options.asJava, table))
    // If DATEFORMAT is not present in load options, check from table properties.
    if (optionsFinal.get("dateformat").isEmpty) {
      optionsFinal.put("dateformat", Maps.getOrDefault(tableProperties,
        "dateformat", CarbonProperties.getInstance
          .getProperty(CarbonCommonConstants.CARBON_DATE_FORMAT,
            CarbonCommonConstants.CARBON_DATE_DEFAULT_FORMAT)))
    }
    // If TIMESTAMPFORMAT is not present in load options, check from table properties.
    if (optionsFinal.get("timestampformat").isEmpty) {
      optionsFinal.put("timestampformat", Maps.getOrDefault(tableProperties,
        "timestampformat", CarbonProperties.getInstance
          .getProperty(CarbonCommonConstants.CARBON_TIMESTAMP_FORMAT,
            CarbonCommonConstants.CARBON_TIMESTAMP_DEFAULT_FORMAT)))
    }
    val partitionStr =
      table.getTableInfo.getFactTable.getPartitionInfo.getColumnSchemaList.asScala.map(
        _.getColumnName.toLowerCase).mkString(",")
    optionsFinal.put(
      "fileheader",
      dataSchema.fields.map(_.name.toLowerCase).mkString(",") + "," + partitionStr)
    optionsFinal.put("header", "false")
    val optionsLocal = new mutable.HashMap[String, String]()
    optionsLocal ++= options
    new CarbonLoadModelBuilder(table).build(
      optionsLocal.toMap.asJava,
      optionsFinal,
      model,
      conf)
    CarbonTableOutputFormat.setOverwrite(conf, options("overwrite").toBoolean)
    if (options.contains(DataLoadProcessorConstants.NO_REARRANGE_OF_ROWS)) {
      model.setLoadWithoutConverterWithoutReArrangeStep(true)
    } else {
      model.setLoadWithoutConverterStep(true)
    }
    val staticPartition = options.getOrElse("staticpartition", null)
    if (staticPartition != null) {
      conf.set("carbon.staticpartition", staticPartition)
    }
    // In case of update query there is chance to remove the older segments, so here we can set
    // the to be deleted segments to mark as delete while updating tablestatus
    val segemntsTobeDeleted = options.get("segmentsToBeDeleted")
    if (segemntsTobeDeleted.isDefined) {
      conf.set(CarbonTableOutputFormat.SEGMENTS_TO_BE_DELETED, segemntsTobeDeleted.get)
    }

    val currPartition = options.getOrElse("currentpartition", null)
    if (currPartition != null) {
      conf.set("carbon.currentpartition", currPartition)
    }
    // Update with the current in progress load.
    val loadEntryOption = CarbonOutputWriter.getObjectFromMap[LoadMetadataDetails](options,
      "currentloadentry")
    loadEntryOption.foreach { loadEntry =>
      model.setSegmentId(loadEntry.getLoadName)
      model.setFactTimeStamp(loadEntry.getLoadStartTime)
      if (!isLoadDetailsContainTheCurrentEntry(
        model.getLoadMetadataDetails.asScala.toArray, loadEntry)) {
        val details =
          SegmentStatusManager.readLoadMetadata(CarbonTablePath.getMetadataPath(model.getTablePath))
        val list = new util.ArrayList[LoadMetadataDetails](details.toList.asJava)
        list.add(loadEntry)
        model.setLoadMetadataDetails(list)
      }
    }
    // Set the update timestamp if user sets in case of update query. It needs to be updated
    // in load status update time
    val updateTimeStamp = options.get("updatetimestamp")
    if (updateTimeStamp.isDefined) {
      conf.set(CarbonTableOutputFormat.UPDATE_TIMESTAMP, updateTimeStamp.get)
    }
    conf.set(CarbonCommonConstants.CARBON_WRITTEN_BY_APPNAME, sparkSession.sparkContext.appName)
    CarbonTableOutputFormat.setLoadModel(conf, model)

    new OutputWriterFactory {

      /**
       * counter used for generating task numbers. This is used to generate unique partition numbers
       * in case of partitioning
       */
      val counter = new AtomicLong()
      val taskIdMap = new ConcurrentHashMap[String, java.lang.Long]()

      override def newInstance(
          path: String,
          dataSchema: StructType,
          context: TaskAttemptContext): OutputWriter = {
        val model = CarbonTableOutputFormat.getLoadModel(context.getConfiguration)
        val appName = context.getConfiguration.get(CarbonCommonConstants.CARBON_WRITTEN_BY_APPNAME)
        CarbonProperties.getInstance().addProperty(
          CarbonCommonConstants.CARBON_WRITTEN_BY_APPNAME, appName)
        val taskNumber = generateTaskNumber(path, context, model.getSegmentId)
        val storeLocation = CommonUtil.getTempStoreLocations(taskNumber)
        CarbonTableOutputFormat.setTempStoreLocations(context.getConfiguration, storeLocation)
        new CarbonOutputWriter(path, context, dataSchema.map(_.dataType), taskNumber, model)
      }

      /**
       * Generate taskid using the taskid of taskcontext and the path. It should be unique in case
       * of partition tables.
       */
      private def generateTaskNumber(path: String,
          context: TaskAttemptContext, segmentId: String): String = {
        var partitionNumber: java.lang.Long = taskIdMap.get(path)
        if (partitionNumber == null) {
          partitionNumber = counter.incrementAndGet()
          // Generate taskid using the combination of taskid and partition number to make it unique.
          taskIdMap.put(path, partitionNumber)
        }
        val taskID = context.getTaskAttemptID.getTaskID.getId
        // In case of compaction the segmentId will be like 1.1. Therefore replacing '.' with ""
        // so that unique number can be generated
        CarbonScalaUtil.generateUniqueNumber(taskID, segmentId.replace(".", ""), partitionNumber)
      }

      override def getFileExtension(context: TaskAttemptContext): String = {
        CarbonTablePath.CARBON_DATA_EXT
      }

    }
  }
  override def equals(other: Any): Boolean = other.isInstanceOf[SparkCarbonTableFormat]

  private def isLoadDetailsContainTheCurrentEntry(
      loadDetails: Array[LoadMetadataDetails],
      currentEntry: LoadMetadataDetails): Boolean = {
    (loadDetails.length - 1 to 0).exists { index =>
      loadDetails(index).getLoadName.equals(currentEntry.getLoadName)
    }
  }
}

case class CarbonSQLHadoopMapReduceCommitProtocol(jobId: String, path: String, isAppend: Boolean)
  extends SQLHadoopMapReduceCommitProtocol(jobId, path, isAppend) {

  override def setupTask(taskContext: TaskAttemptContext): Unit = {
    if (isCarbonDataFlow(taskContext.getConfiguration)) {
      ThreadLocalSessionInfo.setConfigurationToCurrentThread(taskContext.getConfiguration)
    }
    super.setupTask(taskContext)
  }

  /**
   * collect carbon partition info from TaskCommitMessage list
   */
  override def commitJob(jobContext: JobContext,
      taskCommits: Seq[TaskCommitMessage]): Unit = {
    if (isCarbonDataFlow(jobContext.getConfiguration)) {
      var dataSize = 0L
      var indexLen = 0L
      val indexFileNameMap = new util.HashMap[String, util.Set[String]]()
      val partitions =
        taskCommits
          .flatMap { taskCommit =>
            taskCommit.obj match {
              case (map: Map[String, String], _) =>

                val size = map.get("carbon.datasize")
                if (size.isDefined) {
                  dataSize = dataSize + java.lang.Long.parseLong(size.get)
                }
                val indexSize = map.get("carbon.indexsize")
                if (indexSize.isDefined) {
                  indexLen = indexLen + java.lang.Long.parseLong(indexSize.get)
                }
                val indexMapOption = CarbonOutputWriter.getObjectFromMap[util.HashMap[String,
                  Set[String]]](map, "carbon.index.files.name")
                indexMapOption.foreach { indexMap =>
                  indexMap.asScala.foreach { e =>
                    var values: util.Set[String] = indexFileNameMap.get(e._1)
                    if (values == null) {
                      values = new util.HashSet[String]()
                      indexFileNameMap.put(e._1, values)
                    }
                    values.addAll(e._2.asInstanceOf[util.Set[String]])
                  }
                }
                CarbonOutputWriter
                  .getObjectFromMap[util.ArrayList[String]](map, "carbon.partitions")
                  .map(_.asScala.toArray)
                  .getOrElse(Array.empty[String])
              case _ => Array.empty[String]
            }
          }
          .distinct
          .toList
          .asJava

      jobContext.getConfiguration.set("carbon.output.partitions.name",
        ObjectSerializationUtil.convertObjectToString(partitions))
      jobContext.getConfiguration.set("carbon.datasize", dataSize.toString)
      jobContext.getConfiguration.set("carbon.indexsize", indexLen.toString)
      jobContext.getConfiguration.set("carbon.index.files.name",
        ObjectSerializationUtil.convertObjectToString(indexFileNameMap))
      val newTaskCommits = taskCommits.map { taskCommit =>
        taskCommit.obj match {
          case (map: Map[String, String], set) =>
            new TaskCommitMessage(
              map.filterNot(e => "carbon.partitions".equals(e._1) ||
                                 "carbon.datasize".equals(e._1) ||
                                 "carbon.indexsize".equals(e._1) ||
                                 "carbon.index.files.name".equals(e._1)),
              set)
          case _ => taskCommit
        }
      }
      super.commitJob(jobContext, newTaskCommits)
    } else {
      super.commitJob(jobContext, taskCommits)
    }
  }

  /**
   * set carbon partition info into TaskCommitMessage
   */
  override def commitTask(
      taskContext: TaskAttemptContext
  ): FileCommitProtocol.TaskCommitMessage = {
    var taskMsg = super.commitTask(taskContext)
    if (isCarbonDataFlow(taskContext.getConfiguration)) {
      ThreadLocalSessionInfo.unsetAll()
      val partitions: String = taskContext.getConfiguration.get("carbon.output.partitions.name", "")
      val indexFileNameMap = new util.HashMap[String, util.Set[String]]()
      var sum = 0L
      var indexSize = 0L
      if (!StringUtils.isEmpty(partitions)) {
        val partitionList = ObjectSerializationUtil
          .convertStringToObject(partitions)
          .asInstanceOf[util.ArrayList[String]]
          .asScala
        val filesListOption = CarbonOutputWriter.getObjectFromContext[util.ArrayList[String]](
          taskContext, "carbon.output.files.name")
        filesListOption.foreach { filesList =>
          filesList.asScala.foreach { file =>
            if (file.contains(".carbondata")) {
              sum += java.lang.Long.parseLong(file.substring(file.lastIndexOf(":") + 1))
            } else if (file.contains(".carbonindex")) {
              val fileOffset = file.lastIndexOf(":")
              indexSize += java.lang.Long.parseLong(file.substring(fileOffset + 1))
              val absoluteFileName = file.substring(0, fileOffset)
              val indexFileNameOffset = absoluteFileName.lastIndexOf("/")
              val indexFileName = absoluteFileName.substring(indexFileNameOffset + 1)
              val matchedPartition = partitionList.find(absoluteFileName.startsWith)
              var values: util.Set[String] = indexFileNameMap.get(matchedPartition.get)
              if (values == null) {
                values = new util.HashSet[String]()
                indexFileNameMap.put(matchedPartition.get, values)
              }
              values.add(indexFileName)
            }
          }
        }
        val indexFileNames = ObjectSerializationUtil.convertObjectToString(indexFileNameMap)
        taskMsg = taskMsg.obj match {
          case (map: Map[String, String], set) =>
            new TaskCommitMessage(
              map ++ Map("carbon.partitions" -> partitions,
                "carbon.datasize" -> sum.toString,
                "carbon.indexsize" -> indexSize.toString,
                "carbon.index.files.name" -> indexFileNames), set)
          case _ => taskMsg
        }
      }
      // Update outputMetrics with carbondata and index size
      TaskContext.get().taskMetrics().outputMetrics.setBytesWritten(sum + indexSize)
    }
    taskMsg
  }

  override def abortTask(taskContext: TaskAttemptContext): Unit = {
    super.abortTask(taskContext)
    if (isCarbonDataFlow(taskContext.getConfiguration)) {
      val filesListOption = CarbonOutputWriter.getObjectFromContext[util.ArrayList[String]](
        taskContext, "carbon.output.files.name")
      filesListOption.foreach { filesList =>
        filesList.asScala.foreach { file =>
          val outputFile: String = file.substring(0, file.lastIndexOf(":"))
          if (outputFile.endsWith(CarbonTablePath.CARBON_DATA_EXT)) {
            FileFactory
              .deleteAllCarbonFilesOfDir(FileFactory
                .getCarbonFile(outputFile,
                  taskContext.getConfiguration))
          }
        }
      }
      ThreadLocalSessionInfo.unsetAll()
    }
  }

  override def newTaskTempFileAbsPath(taskContext: TaskAttemptContext,
      absoluteDir: String,
      ext: String): String = {
    if (isCarbonFileFlow(taskContext.getConfiguration) ||
        isCarbonDataFlow(taskContext.getConfiguration)) {
      super.newTaskTempFile(taskContext, Some(absoluteDir), ext)
    } else {
      super.newTaskTempFileAbsPath(taskContext, absoluteDir, ext)
    }
  }

  /**
   * set carbon temp folder to task temp folder
   */
  override def newTaskTempFile(
      taskContext: TaskAttemptContext,
      dir: Option[String],
      ext: String): String = {
    if (isCarbonDataFlow(taskContext.getConfiguration)) {
      val path = super.newTaskTempFile(taskContext, dir, ext)
      taskContext.getConfiguration.set("carbon.newTaskTempFile.path", path)
      val model = CarbonTableOutputFormat.getLoadModel(taskContext.getConfiguration)
      val partitions = CarbonOutputWriter.getPartitionsFromPath(
        path, taskContext, model).map(ExternalCatalogUtils.unescapePathName)
      val updatedPartitions = if (partitions.nonEmpty) {
        val linkedMap = mutable.LinkedHashMap[String, String]()
        val updatedPartitions = partitions.map(CarbonOutputWriter.splitPartition)
        updatedPartitions.foreach {
          case (k, v) => linkedMap.put(k, v)
        }
        linkedMap
      } else {
        mutable.LinkedHashMap.empty[String, String]
      }
      val writePath =
        CarbonOutputWriter.getPartitionPath(path, taskContext, model, updatedPartitions)
      writePath + "/" + model.getSegmentId + "_" + model.getFactTimeStamp + ".tmp"
    } else {
      super.newTaskTempFile(taskContext, dir, ext)
    }

  }

  private def isCarbonFileFlow(conf: Configuration): Boolean = {
    conf.get("carbon.commit.protocol") != null
  }

  private def isCarbonDataFlow(conf: Configuration): Boolean = {
    conf.get("carbondata.commit.protocol") != null
  }
}

/**
 * It is a just class to make compile between spark 2.1 and 2.2
 */
private trait AbstractCarbonOutputWriter {
  def write(row: Row): Unit = throw new UnsupportedOperationException("call writeInternal")
  def writeInternal(row: InternalRow): Unit = {
    writeCarbon(row)
  }
  def write(row: InternalRow): Unit = {
    writeCarbon(row)
  }
  def writeCarbon(row: InternalRow): Unit
}

private class CarbonOutputWriter(path: String,
    context: TaskAttemptContext,
    nonPartitionFieldTypes: Seq[DataType],
    taskNo : String,
    model: CarbonLoadModel)
  extends OutputWriter with AbstractCarbonOutputWriter {
  var actualPath = path
  var tmpPath = context.getConfiguration.get("carbon.newTaskTempFile.path", actualPath)
  val converter = new DataTypeConverterImpl

  val partitions = CarbonOutputWriter
    .getPartitionsFromPath(tmpPath, context, model)
    .map(ExternalCatalogUtils.unescapePathName)

  val staticPartition = CarbonOutputWriter
    .getObjectFromContext[util.HashMap[String, Boolean]](context, "carbon.staticpartition")
    .getOrElse(null)

  val currPartitions = CarbonOutputWriter
    .getObjectFromContext[util.List[indexstore.PartitionSpec]](context, "carbon.currentpartition")
    .getOrElse(new util.ArrayList[indexstore.PartitionSpec]())

  var (updatedPartitions, partitionData) = if (partitions.nonEmpty) {
    val linkedMap = mutable.LinkedHashMap[String, String]()
    val updatedPartitions = partitions.map(CarbonOutputWriter.splitPartition)
    updatedPartitions.foreach {
      case (k, v) => linkedMap.put(k, v)
    }
    (linkedMap, CarbonOutputWriter.updatePartitions(
      updatedPartitions.map(_._2), model, staticPartition, converter))
  } else {
    val tempUpdatedPartitions = mutable.LinkedHashMap.empty[String, String]
    var tempPartitionData = Array.empty[AnyRef]
    val updatePath = CarbonOutputWriter.getPartitionPath(
      tmpPath, context, model, tempUpdatedPartitions)
    val writeSpec = new indexstore.PartitionSpec(null, updatePath)
    val index = currPartitions.indexOf(writeSpec)
    if (index > -1) {
      val spec = currPartitions.get(index)
      spec.getPartitions.asScala.map(CarbonOutputWriter.splitPartition).foreach {
        case (k, v) => tempUpdatedPartitions.put(k, v)
      }
      tempPartitionData = CarbonOutputWriter.updatePartitions(
        tempUpdatedPartitions.map(_._2).toSeq, model, staticPartition, converter)
    }
    actualPath = updatePath + "/" + model.getSegmentId + "_" + model.getFactTimeStamp + ".tmp"
    (tempUpdatedPartitions, tempPartitionData)
  }

  val writable = new ObjectArrayWritable

  private val recordWriter: CarbonRecordWriter = {
    context.getConfiguration.set("carbon.outputformat.taskno", taskNo)
    context.getConfiguration.set("carbon.outputformat.writepath", actualPath)
    new CarbonTableOutputFormat() {
      override def getDefaultWorkFile(context: TaskAttemptContext, extension: String): Path = {
        new Path(tmpPath)
      }
    }.getRecordWriter(context).asInstanceOf[CarbonRecordWriter]
  }

  // TODO Implement write support interface to support writing Row directly to record writer
  def writeCarbon(row: InternalRow): Unit = {
    val numOfColumns = nonPartitionFieldTypes.length + partitionData.length
    val data: Array[AnyRef] = CommonUtil.getObjectArrayFromInternalRowAndConvertComplexType(
      row,
      nonPartitionFieldTypes,
      numOfColumns)
    if (partitionData.length > 0) {
      System.arraycopy(partitionData, 0, data, nonPartitionFieldTypes.length, partitionData.length)
    }
    writable.set(data)
    recordWriter.write(NullWritable.get(), writable)
  }

  override def writeInternal(row: InternalRow): Unit = {
    writeCarbon(row)
  }

  override def close(): Unit = {
    recordWriter.close(context)
    ThreadLocalSessionInfo.setConfigurationToCurrentThread(context.getConfiguration)
  }
}


object CarbonOutputWriter {

  def  getObjectFromContext[T](context: TaskAttemptContext, key: String): Option[T] = {
    val config = context.getConfiguration.get(key)
    if (!StringUtils.isEmpty(config)) {
      Option(ObjectSerializationUtil.convertStringToObject(config).asInstanceOf[T])
    } else {
      None
    }
  }

  def getObjectFromMap[T](map: Map[String, String], key: String): Option[T] = {
    val config = map.get(key)
    if (config.isDefined) {
      Option(ObjectSerializationUtil.convertStringToObject(config.get).asInstanceOf[T])
    } else {
      None
    }
  }

  def getPartitionsFromPath(
      path: String,
      attemptContext: TaskAttemptContext,
      model: CarbonLoadModel): Array[String] = {
    val attemptId = attemptContext.getTaskAttemptID.toString + "/"
    if (path.indexOf(attemptId) > -1) {
      val str = path.substring(path.indexOf(attemptId) + attemptId.length, path.lastIndexOf("/"))
      if (str.length > 0) {
        str.split("/")
      } else {
        Array.empty
      }
    } else {
      Array.empty
    }
  }

  def splitPartition(p: String): (String, String) = {
    val value = p.substring(p.indexOf("=") + 1, p.length)
    val col = p.substring(0, p.indexOf("="))
    // NUll handling case. For null hive creates with this special name
    if (value.equals("__HIVE_DEFAULT_PARTITION__")) {
      (col, null)
      // we should replace back the special string with empty value.
    } else if (value.equals(CarbonCommonConstants.MEMBER_DEFAULT_VAL)) {
      (col, "")
    } else {
      (col, value)
    }
  }

  /**
   * update partition folder path
   */
  def updatePartitions(
      partitionData: Seq[String],
      model: CarbonLoadModel,
      staticPartition: util.HashMap[String, Boolean],
      converter: DataTypeConverter
  ): Array[AnyRef] = {
    model.getCarbonDataLoadSchema.getCarbonTable.getTableInfo.getFactTable.getPartitionInfo
      .getColumnSchemaList.asScala.zipWithIndex.map { case (col, index) =>

      val dataType = if (col.getDataType.equals(DataTypes.DATE)) {
        DataTypes.INT
      } else if (col.getDataType.equals(DataTypes.TIMESTAMP) ||
                 col.getDataType.equals(DataTypes.DATE)) {
        DataTypes.LONG
      } else {
        col.getDataType
      }
      if (staticPartition != null && staticPartition.get(col.getColumnName.toLowerCase)) {
        // TODO: why not use CarbonScalaUtil.convertToDateAndTimeFormats ?
        val convertedValue =
          CarbonScalaUtil.convertStaticPartitions(partitionData(index), col)
        if (col.getDataType.equals(DataTypes.DATE)) {
          convertedValue.toInt.asInstanceOf[AnyRef]
        } else {
          DataTypeUtil.getDataBasedOnDataType(
            convertedValue,
            dataType,
            converter)
        }
      } else {
        DataTypeUtil.getDataBasedOnDataType(partitionData(index), dataType, converter)
      }
    }.toArray
  }

  def getPartitionPath(path: String,
      attemptContext: TaskAttemptContext,
      model: CarbonLoadModel,
      updatedPartitions: mutable.LinkedHashMap[String, String]
  ): String = {
    if (updatedPartitions.nonEmpty) {
      // All dynamic partitions need to be converted to proper format
      val formattedPartitions = CarbonScalaUtil.updatePartitions(
        updatedPartitions.asInstanceOf[mutable.LinkedHashMap[String, String]],
        model.getCarbonDataLoadSchema.getCarbonTable)
      val partitionString = formattedPartitions.map { p =>
        ExternalCatalogUtils.escapePathName(p._1) + "=" + ExternalCatalogUtils.escapePathName(p._2)
      }.mkString(CarbonCommonConstants.FILE_SEPARATOR)
      model.getCarbonDataLoadSchema.getCarbonTable.getTablePath +
      CarbonCommonConstants.FILE_SEPARATOR + partitionString
    } else {
      var updatedPath = FileFactory.getUpdatedFilePath(path)
      updatedPath.substring(0, updatedPath.lastIndexOf("/"))
    }
  }
}

