// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "salsa/try_touch_experiment/property.h"

using base::SplitString;
using base::StringPrintf;
using std::string;
using std::vector;

Property::Property() : is_valid_(false) {}

bool Property::valid() const {
  return is_valid_;
}

Property::Property(string const &property_string) : is_valid_(false) {
  vector<string> parts;
  SplitString(property_string, ':', &parts);

  name_ = "";
  if (parts.size() == 2) {
    // Check that the property name contains only legal characters
    is_valid_ = (parts[0].length() > 0);
    for (size_t i = 0; i < parts[0].length(); i++) {
      is_valid_ &= (IsAsciiAlpha(parts[0][i]) || IsAsciiDigit(parts[0][i]) ||
                    parts[0][i] == ' ' || parts[0][i] == '-');
    }

    if (is_valid_) {
      name_ = parts[0];
      value_ = atof(parts[1].c_str());
      old_value_ = GetCurrentValue();
    }
  }
}

bool Property::Reset() const {
  return SetValue(old_value_);
}

bool Property::Apply() const {
  return SetValue(value_);
}

bool Property::SetValue(double new_value) const {
  // Connect to the X display and device we need
  Display *display = GetX11Display();
  XDevice *device = GetX11TouchpadDevice(display);
  if (!display || !device)
    return false;

  // Find the id of the property we want
  Atom this_prop = XInternAtom(display, name_.c_str(), true);

  // Select the property and see what format it is in
  Atom type;
  int format;
  unsigned long nitems, bytes_after;  // NOLINT(runtime/int)
  unsigned char *data;
  unsigned char *new_data = NULL;
  if (XGetDeviceProperty(display, device, this_prop, 0, 1000, False,
                         AnyPropertyType, &type, &format,
                         &nitems, &bytes_after, &data) == Success) {
    if (nitems == 1) {
      // Re-format the value into the type X is expecting
      int8_t int8_t_val = (int8_t)new_value;
      int16_t int16_t_val = (int16_t)new_value;
      int32_t int32_t_val = (int32_t)new_value;
      float float_val = static_cast<float>(new_value);
      Atom float_atom = XInternAtom(display, "FLOAT", True);
      if (type == XA_INTEGER) {
        switch (format) {
          case 8: new_data = (unsigned char*)&int8_t_val; break;
          case 16: new_data = (unsigned char*)&int16_t_val; break;
          case 32: new_data = (unsigned char*)&int32_t_val; break;
        }
      } else if (float_atom != None && type == float_atom) {
        new_data = (unsigned char*)&float_val;
      }

      // If everything went okay, apply the change
      if (new_data) {
        XChangeDeviceProperty(display, device, this_prop, type, format,
                              PropModeReplace, new_data, 1);
      }
    }
  }

  // Clean up
  XCloseDevice(display, device);
  XCloseDisplay(display);

  return (new_data != NULL);
}

Display* Property::GetX11Display() const {
  return XOpenDisplay(NULL);
}

XDevice* Property::GetX11TouchpadDevice(Display *display) const {
  if (!display)
    return NULL;

  // Get a list of the details of all the X devices available
  int num_device_infos;
  XDeviceInfo *device_infos = XListInputDevices(display, &num_device_infos);

  // Go through the list and find our touchpad
  XDevice *touchpad_device = NULL;
  for (int i = 0; i < num_device_infos; i++) {
    if (device_infos[i].use != IsXExtensionPointer)
      continue;

    XDevice *tmp_device = XOpenDevice(display, device_infos[i].id);
    if (!tmp_device)
      continue;

    // The touchpad will have a "Device Touchpad" Property set to 1.0
    double val = GetPropertyValue(display, tmp_device, "Device Touchpad");
    if (val == 1.0) {
      touchpad_device = tmp_device;
      break;
    } else {
      XCloseDevice(display, tmp_device);
    }
  }

  return touchpad_device;
}

double Property::GetPropertyValue(Display *display, XDevice *device,
                                  const char* name) const {
  // Find the id of the property we want
  Atom this_prop = XInternAtom(display, name, true);

  // Parse the value of this property
  Atom type;
  int format;
  unsigned long nitems, bytes_after;  // NOLINT(runtime/int)
  unsigned char *data;
  double val = -1;
  if (XGetDeviceProperty(display, device, this_prop, 0, 1000, False,
                         AnyPropertyType, &type, &format,
                         &nitems, &bytes_after, &data) == Success) {
    if (nitems == 1) {
      Atom float_atom = XInternAtom(display, "FLOAT", True);
      if (type == XA_INTEGER) {
        switch (format) {
          case 8: val = *(reinterpret_cast<const int8_t*>(data)); break;
          case 16: val = *(reinterpret_cast<const int16_t*>(data)); break;
          case 32: val = *(reinterpret_cast<const int32_t*>(data)); break;
        }
      } else if (float_atom != None && type == float_atom) {
        val = *(reinterpret_cast<const float*>(data));
      }
    }
  }

  return val;
}

double Property::GetCurrentValue() const {
  Display *display = GetX11Display();
  XDevice *device = GetX11TouchpadDevice(display);
  if (!display || !device)
    return -1.0;

  double val = GetPropertyValue(display, device, name_.c_str());

  XCloseDevice(display, device);
  XCloseDisplay(display);
  return val;
}
