/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * 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.
 */

#include "private/resources.h"

#include <fcntl.h>
#include <linux/fb.h>
#include <linux/kd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>

#include <limits>
#include <memory>
#include <regex>
#include <string>
#include <vector>

<<<<<<< HEAD
//#include <android-base/stringprintf.h> // does not exist in 6.0
//#include <android-base/strings.h> // does not exist in 6.0
=======
#include <android-base/strings.h>
>>>>>>> android-10.0.0_r25
#include <png.h>

#include "minui/minui.h"

static std::string g_resource_dir{ "/res/images" };

std::unique_ptr<GRSurface> GRSurface::Create(size_t width, size_t height, size_t row_bytes,
                                             size_t pixel_bytes) {
  if (width == 0 || row_bytes == 0 || height == 0 || pixel_bytes == 0) return nullptr;
  if (std::numeric_limits<size_t>::max() / row_bytes < height) return nullptr;

  // Cannot use std::make_unique to access non-public ctor.
  auto result = std::unique_ptr<GRSurface>(new GRSurface(width, height, row_bytes, pixel_bytes));
  size_t data_size = row_bytes * height;
  result->data_size_ =
      (data_size + kSurfaceDataAlignment - 1) / kSurfaceDataAlignment * kSurfaceDataAlignment;
  result->data_.reset(
      static_cast<uint8_t*>(aligned_alloc(kSurfaceDataAlignment, result->data_size_)));
  if (!result->data_) return nullptr;
  return result;
}

std::unique_ptr<GRSurface> GRSurface::Clone() const {
  auto result = GRSurface::Create(width, height, row_bytes, pixel_bytes);
  if (!result) return nullptr;
  memcpy(result->data(), data(), data_size_);
  return result;
}

<<<<<<< HEAD
PngHandler::PngHandler(const std::string& name) : error_code_(0), png_fp_(nullptr, fclose) {
  char res_path[PATH_MAX];
  sprintf(res_path, "/res/images/%s.png", name.c_str());
  //std::string res_path = sprintf("/res/images/%s.png", name.c_str());
  png_fp_.reset(fopen(res_path, "rbe"));
=======
PngHandler::PngHandler(const std::string& name) {
  std::string res_path = g_resource_dir + "/" + name + ".png";
  png_fp_.reset(fopen(res_path.c_str(), "rbe"));
  // Try to read from |name| if the resource path does not work.
  if (!png_fp_) {
    png_fp_.reset(fopen(name.c_str(), "rbe"));
  }
>>>>>>> android-10.0.0_r25
  if (!png_fp_) {
    error_code_ = -1;
    return;
  }

  uint8_t header[8];
  size_t bytesRead = fread(header, 1, sizeof(header), png_fp_.get());
  if (bytesRead != sizeof(header)) {
    error_code_ = -2;
    return;
  }

  if (png_sig_cmp(header, 0, sizeof(header))) {
    error_code_ = -3;
    return;
  }

  png_ptr_ = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
  if (!png_ptr_) {
    error_code_ = -4;
    return;
  }

  info_ptr_ = png_create_info_struct(png_ptr_);
  if (!info_ptr_) {
    error_code_ = -5;
    return;
  }

  if (setjmp(png_jmpbuf(png_ptr_))) {
    error_code_ = -6;
    return;
  }

  png_init_io(png_ptr_, png_fp_.get());
  png_set_sig_bytes(png_ptr_, sizeof(header));
  png_read_info(png_ptr_, info_ptr_);

  png_get_IHDR(png_ptr_, info_ptr_, &width_, &height_, &bit_depth_, &color_type_, nullptr, nullptr,
               nullptr);

  channels_ = png_get_channels(png_ptr_, info_ptr_);

  if (bit_depth_ == 8 && channels_ == 3 && color_type_ == PNG_COLOR_TYPE_RGB) {
    // 8-bit RGB images: great, nothing to do.
  } else if (bit_depth_ <= 8 && channels_ == 1 && color_type_ == PNG_COLOR_TYPE_GRAY) {
    // 1-, 2-, 4-, or 8-bit gray images: expand to 8-bit gray.
    png_set_expand_gray_1_2_4_to_8(png_ptr_);
  } else if (bit_depth_ <= 8 && channels_ == 1 && color_type_ == PNG_COLOR_TYPE_PALETTE) {
    // paletted images: expand to 8-bit RGB.  Note that we DON'T
    // currently expand the tRNS chunk (if any) to an alpha
    // channel, because minui doesn't support alpha channels in
    // general.
    png_set_palette_to_rgb(png_ptr_);
    channels_ = 3;
  } else {
    fprintf(stderr, "minui doesn't support PNG depth %d channels %d color_type %d\n", bit_depth_,
            channels_, color_type_);
    error_code_ = -7;
  }
}

PngHandler::~PngHandler() {
  if (png_ptr_) {
    png_destroy_read_struct(&png_ptr_, &info_ptr_, nullptr);
  }
}

// "display" surfaces are transformed into the framebuffer's required pixel format (currently only
// RGBX is supported) at load time, so gr_blit() can be nothing more than a memcpy() for each row.

// Copies 'input_row' to 'output_row', transforming it to the framebuffer pixel format. The input
// format depends on the value of 'channels':
//
//   1 - input is 8-bit grayscale
//   3 - input is 24-bit RGB
//   4 - input is 32-bit RGBA/RGBX
//
// 'width' is the number of pixels in the row.
static void TransformRgbToDraw(const uint8_t* input_row, uint8_t* output_row, int channels,
                               int width) {
  const uint8_t* ip = input_row;
  uint8_t* op = output_row;

  switch (channels) {
    case 1:
      // expand gray level to RGBX
      for (int x = 0; x < width; ++x) {
        *op++ = *ip;
        *op++ = *ip;
        *op++ = *ip;
        *op++ = 0xff;
        ip++;
      }
      break;

    case 3:
      // expand RGBA to RGBX
      for (int x = 0; x < width; ++x) {
        *op++ = *ip++;
        *op++ = *ip++;
        *op++ = *ip++;
        *op++ = 0xff;
      }
      break;

    case 4:
      // copy RGBA to RGBX
      memcpy(output_row, input_row, width * 4);
      break;
  }
}

int res_create_display_surface(const char* name, GRSurface** pSurface) {
  *pSurface = nullptr;

  PngHandler png_handler(name);
  if (!png_handler) return png_handler.error_code();

  png_structp png_ptr = png_handler.png_ptr();
  png_uint_32 width = png_handler.width();
  png_uint_32 height = png_handler.height();

  auto surface = GRSurface::Create(width, height, width * 4, 4);
  if (!surface) {
    return -8;
  }

  PixelFormat pixel_format = gr_pixel_format();
  if (pixel_format == PixelFormat::ABGR || pixel_format == PixelFormat::BGRA) {
    png_set_bgr(png_ptr);
  }

  for (png_uint_32 y = 0; y < height; ++y) {
    std::vector<uint8_t> p_row(width * 4);
    png_read_row(png_ptr, p_row.data(), nullptr);
    TransformRgbToDraw(p_row.data(), surface->data() + y * surface->row_bytes,
                       png_handler.channels(), width);
  }

  *pSurface = surface.release();

  return 0;
}

int res_create_multi_display_surface(const char* name, int* frames, int* fps,
                                     GRSurface*** pSurface) {
  *pSurface = nullptr;
  *frames = -1;

  PngHandler png_handler(name);
  if (!png_handler) return png_handler.error_code();

  png_structp png_ptr = png_handler.png_ptr();
  png_uint_32 width = png_handler.width();
  png_uint_32 height = png_handler.height();

  *frames = 1;
  *fps = 20;
  png_textp text;
  int num_text;
  if (png_get_text(png_ptr, png_handler.info_ptr(), &text, &num_text)) {
    for (int i = 0; i < num_text; ++i) {
      if (text[i].key && strcmp(text[i].key, "Frames") == 0 && text[i].text) {
        *frames = atoi(text[i].text);
      } else if (text[i].key && strcmp(text[i].key, "FPS") == 0 && text[i].text) {
        *fps = atoi(text[i].text);
      }
    }
    printf("  found frames = %d\n", *frames);
    printf("  found fps = %d\n", *fps);
  }

  int result = 0;
  GRSurface** surface = nullptr;
  if (*frames <= 0 || *fps <= 0) {
    printf("bad number of frames (%d) and/or FPS (%d)\n", *frames, *fps);
    result = -10;
    goto exit;
  }

  if (height % *frames != 0) {
    printf("bad height (%d) for frame count (%d)\n", height, *frames);
    result = -9;
    goto exit;
  }

  surface = static_cast<GRSurface**>(calloc(*frames, sizeof(GRSurface*)));
  if (!surface) {
    result = -8;
    goto exit;
  }
  for (int i = 0; i < *frames; ++i) {
    auto created_surface = GRSurface::Create(width, height / *frames, width * 4, 4);
    if (!created_surface) {
      result = -8;
      goto exit;
    }
    surface[i] = created_surface.release();
  }

  if (gr_pixel_format() == PixelFormat::ABGR || gr_pixel_format() == PixelFormat::BGRA) {
    png_set_bgr(png_ptr);
  }

  for (png_uint_32 y = 0; y < height; ++y) {
    std::vector<uint8_t> p_row(width * 4);
    png_read_row(png_ptr, p_row.data(), nullptr);
    int frame = y % *frames;
    uint8_t* out_row = surface[frame]->data() + (y / *frames) * surface[frame]->row_bytes;
    TransformRgbToDraw(p_row.data(), out_row, png_handler.channels(), width);
  }

  *pSurface = surface;

exit:
  if (result < 0) {
    if (surface) {
      for (int i = 0; i < *frames; ++i) {
        free(surface[i]);
      }
      free(surface);
    }
  }
  return result;
}

int res_create_multi_display_surface(const char* name, int* frames,
        GRSurface*** pSurface) {
    int fps = 0;
    return res_create_multi_display_surface(name, frames, &fps, pSurface);
}

int res_create_alpha_surface(const char* name, GRSurface** pSurface) {
  *pSurface = nullptr;

  PngHandler png_handler(name);
  if (!png_handler) return png_handler.error_code();

  if (png_handler.channels() != 1) {
    return -7;
  }

  png_structp png_ptr = png_handler.png_ptr();
  png_uint_32 width = png_handler.width();
  png_uint_32 height = png_handler.height();

  auto surface = GRSurface::Create(width, height, width, 1);
  if (!surface) {
    return -8;
  }

  PixelFormat pixel_format = gr_pixel_format();
  if (pixel_format == PixelFormat::ABGR || pixel_format == PixelFormat::BGRA) {
    png_set_bgr(png_ptr);
  }

  for (png_uint_32 y = 0; y < height; ++y) {
    uint8_t* p_row = surface->data() + y * surface->row_bytes;
    png_read_row(png_ptr, p_row, nullptr);
  }

  *pSurface = surface.release();

  return 0;
}

void res_set_resource_dir(const std::string& dirname) {
  g_resource_dir = dirname;
}

// This function tests if a locale string stored in PNG (prefix) matches
// the locale string provided by the system (locale).
bool matches_locale(const std::string& prefix, const std::string& locale) {
  // According to the BCP 47 format, A locale string may consists of:
  // language-{extlang}-{script}-{region}-{variant}
  // The locale headers in PNG mostly consist of language-{region} except for sr-Latn, and some
  // android's system locale can have the format language-{script}-{region}.

  // Return true if the whole string of prefix matches the top part of locale. Otherwise try to
  // match the locale string without the {script} section.
  // For instance, prefix == "en" matches locale == "en-US", prefix == "sr-Latn" matches locale
  // == "sr-Latn-BA", and prefix == "zh-CN" matches locale == "zh-Hans-CN".
  //if (android::base::StartsWith(locale, prefix)) { // does not exist in 6.0
  if (strncmp(prefix.c_str(), locale.c_str(), prefix.length()) == 0) {
    return true;
  }

  size_t separator = prefix.find('-');
  if (separator == std::string::npos) {
    return false;
  }
  std::regex loc_regex(prefix.substr(0, separator) + "-[A-Za-z]*" + prefix.substr(separator));
  return std::regex_match(locale, loc_regex);
}

std::vector<std::string> get_locales_in_png(const std::string& png_name) {
  PngHandler png_handler(png_name);
  if (!png_handler) {
    printf("Failed to open %s, error: %d\n", png_name.c_str(), png_handler.error_code());
    return {};
  }
  if (png_handler.channels() != 1) {
    printf("Expect input png to have 1 data channel, this file has %d\n", png_handler.channels());
    return {};
  }

  std::vector<std::string> result;
  std::vector<uint8_t> row(png_handler.width());
  for (png_uint_32 y = 0; y < png_handler.height(); ++y) {
    png_read_row(png_handler.png_ptr(), row.data(), nullptr);
    int h = (row[3] << 8) | row[2];
    std::string loc(reinterpret_cast<char*>(&row[5]));
    if (!loc.empty()) {
      result.push_back(loc);
    }
    for (int i = 0; i < h; ++i, ++y) {
      png_read_row(png_handler.png_ptr(), row.data(), nullptr);
    }
  }

  return result;
}

int res_create_localized_alpha_surface(const char* name,
                                       const char* locale,
                                       GRSurface** pSurface) {
  *pSurface = nullptr;
  if (locale == nullptr) {
    return 0;
  }

  PngHandler png_handler(name);
  if (!png_handler) return png_handler.error_code();

  if (png_handler.channels() != 1) {
    return -7;
  }

  png_structp png_ptr = png_handler.png_ptr();
  png_uint_32 width = png_handler.width();
  png_uint_32 height = png_handler.height();

  for (png_uint_32 y = 0; y < height; ++y) {
    std::vector<uint8_t> row(width);
    png_read_row(png_ptr, row.data(), nullptr);
    int w = (row[1] << 8) | row[0];
    int h = (row[3] << 8) | row[2];
    __unused int len = row[4];
    char* loc = reinterpret_cast<char*>(&row[5]);

    if (y + 1 + h >= height || matches_locale(loc, locale)) {
      printf("  %20s: %s (%d x %d @ %d)\n", name, loc, w, h, y);

      auto surface = GRSurface::Create(w, h, w, 1);
      if (!surface) {
        return -8;
      }

      for (int i = 0; i < h; ++i, ++y) {
        png_read_row(png_ptr, row.data(), nullptr);
        memcpy(surface->data() + i * w, row.data(), w);
      }

      *pSurface = surface.release();
      break;
    }

    for (int i = 0; i < h; ++i, ++y) {
      png_read_row(png_ptr, row.data(), nullptr);
    }
  }

  return 0;
}

void res_free_surface(GRSurface* surface) {
  free(surface);
}
