/*
 * Copyright (C) 2019 MediaTek Inc.
 *
 * Licensed 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.
 */
#define LOG_TAG "MediaEntity"

#include <mtklibv4l2/MediaEntity.h>

#include <fcntl.h>
#include <sstream>
#include <string.h>
#include <unistd.h>

#include <memory>
#include <string>

using cros::V4L2Device;
using cros::V4L2Subdevice;
using cros::V4L2VideoNode;

using NSCam::BAD_VALUE;
using NSCam::NAME_NOT_FOUND;
using NSCam::NO_ERROR;
using NSCam::NO_INIT;
using NSCam::OK;
using NSCam::PERMISSION_DENIED;
using NSCam::status_t;
using NSCam::UNKNOWN_ERROR;

MediaEntity::MediaEntity(const struct media_entity_desc& entity,
                         struct media_link_desc* links,
                         struct media_pad_desc* pads)
    : mInfo(entity), mDevice(nullptr) {
  LOGD("@%s: %s, id: %d", __FUNCTION__, entity.name, entity.id);
  mLinks.reserve(entity.links);
  mPads.reserve(entity.pads);
  mLinks.clear();
  mPads.clear();

  if (links != nullptr) {
    for (int i = 0; i < entity.links; i++) {
      LOGD("link %d: src entity %d: %d --> sink entity %d:%d (%s%s%s)", i,
           links[i].source.entity, links[i].source.index, links[i].sink.entity,
           links[i].sink.index,
           (links[i].flags & MEDIA_LNK_FL_ENABLED) ? "enabled" : "disabled",
           (links[i].flags & MEDIA_LNK_FL_IMMUTABLE) ? " immutable" : "",
           (links[i].flags & MEDIA_LNK_FL_DYNAMIC) ? " dynamic" : "");
      mLinks.push_back(links[i]);
    }
  }

  if (pads != nullptr) {
    for (int i = 0; i < entity.pads; i++) {
      LOGD("pad %d (%s)", pads[i].index,
           (pads[i].flags & MEDIA_PAD_FL_SINK) ? "SINK" : "SOURCE");
      mPads.push_back(pads[i]);
    }
  }
}

MediaEntity::~MediaEntity() {
  LOGD("@%s", __FUNCTION__);
  mInfo = {};
  mLinks.clear();
  mPads.clear();

  if (mDevice != nullptr) {
    if (mDevice->IsOpened())
      mDevice->Close();
    mDevice.reset();
    mDevice = nullptr;
  }
}

status_t MediaEntity::getDevice(std::shared_ptr<V4L2Device>* device) {
  LOGD("@%s", __FUNCTION__);
  status_t status = NO_ERROR;

  if (mDevice == nullptr || !mDevice->IsOpened()) {
    LOGD("Opening device");
    status = openDevice(&mDevice);
  }

  LOGD("device has Opened");
  if (status == NO_ERROR)
    *device = mDevice;
  else
    *device = nullptr;

  return status;
}

status_t MediaEntity::openDevice(std::shared_ptr<V4L2Device>* device) {
  LOGD("@%s, major:minor %d:%d ", __FUNCTION__, mInfo.v4l.major,
       mInfo.v4l.minor);
  status_t status = UNKNOWN_ERROR;
  int ret = 0;
  char sysname[1024];
  int major = mInfo.v4l.major;
  int minor = mInfo.v4l.minor;
  std::ostringstream stringStream;
  stringStream << "/sys/dev/char/" << major << ":" << minor;
  std::string devNameStr = stringStream.str();
  ret = readlink(devNameStr.c_str(), sysname, sizeof(sysname));
  if (ret < 0) {
    LOGE("Unable to find device node");
  } else {
    sysname[ret] = 0;
    char* lastSlash = strrchr(sysname, '/');
    if (lastSlash == nullptr) {
      LOGE("Invalid sysfs device path");
      return status;
    }
    stringStream.str("");
    stringStream << "/dev/" << lastSlash + 1;
    devNameStr = stringStream.str();
    const char* devname = devNameStr.c_str();
    LOGD("Device node : %s", devname);

    (*device).reset();
    if (mInfo.type == MEDIA_ENT_T_DEVNODE_V4L) {
      *device = std::static_pointer_cast<V4L2Device>(
          std::make_shared<V4L2VideoNode>(devname));
    } else {
      *device = std::static_pointer_cast<V4L2Device>(
          std::make_shared<V4L2Subdevice>(devname));
    }
    status = (*device)->Open(O_RDWR);
    if (status != NO_ERROR) {
      LOGE("Failed to open device %s", devname);
      (*device).reset();
    }
  }
  return status;
}

void MediaEntity::updateLinks(const struct media_link_desc* links) {
  LOGD("@%s", __FUNCTION__);

  mLinks.clear();
  for (int i = 0; i < mInfo.links; i++) {
    LOGD("link %d: pad %d --> sink entity %d:%d (%s%s%s)", i,
         links[i].source.index, links[i].sink.entity, links[i].sink.index,
         (links[i].flags & MEDIA_LNK_FL_ENABLED) ? "enabled" : "disabled",
         (links[i].flags & MEDIA_LNK_FL_IMMUTABLE) ? " immutable" : "",
         (links[i].flags & MEDIA_LNK_FL_DYNAMIC) ? " dynamic" : "");

    mLinks.push_back(links[i]);
  }
}

V4L2DeviceType MediaEntity::getType() {
  LOGD("@%s", __FUNCTION__);

  switch (mInfo.type) {
    case MEDIA_ENT_T_DEVNODE_V4L:
      return DEVICE_VIDEO;
      break;
    case MEDIA_ENT_T_V4L2_SUBDEV:
      return SUBDEV_GENERIC;
      break;
    case MEDIA_ENT_T_V4L2_SUBDEV_SENSOR:
      return SUBDEV_SENSOR;
      break;
    case MEDIA_ENT_T_V4L2_SUBDEV_FLASH:
      return SUBDEV_FLASH;
      break;
    case MEDIA_ENT_T_V4L2_SUBDEV_LENS:
      return SUBDEV_LENS;
      break;
    default:
      LOGE("Unknown media entity type: %d", mInfo.type);
      return UNKNOWN_TYPE;
  }
}
