/*
 *
 *  Adapter Implementation of bluez5 for libtdebluez
 *
 *  Copyright (C) 2018  Emanoil Kotsev <deloptes@gmail.com>
 *
 *
 *  This file is part of libtdebluez.
 *
 *  libtdebluez is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  libtdebluez is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with kbluetooth; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#include <linux/rfkill.h>
#include <unistd.h>

#include <tqfile.h>
#include <tqregexp.h>
#include <tqdir.h>

#include <tqdbusproxy.h>
#include <tqmessagebox.h>
#include <tdelocale.h>

#include "adapterImpl.h"

namespace TDEBluetooth
{

AdapterImpl::AdapterImpl(const TQString& service, const TQString& path, TQObject* parent, const char* name) :
        Adapter1Proxy(service, path, parent, name) /*,properties(service,path,parent,name)*/
{
}

AdapterImpl::~AdapterImpl()
{
}

void AdapterImpl::powerOn(bool state)
{
    //	https://www.kernel.org/doc/Documentation/rfkill.txt
    //  http://jwhsmith.net/2015/02/manipulating-rfkill-using-devices-programmatically/
    //  https://cpp.hotexamples.com/examples/-/-/rfkill_alloc/cpp-rfkill_alloc-function-examples.html
    //  https://github.com/systemd/systemd/blob/main/src/rfkill/rfkill.c

    TQString device = getPath();
    device = device.replace(TQRegExp("^/.*/"), "");
    int hcidx = -1;
    TQDir d("/sys/class/rfkill");
    d.setFilter(TQDir::Dirs);
    for (int i = 0; i < d.count(); i++)
    {
        // expected is rfkill<n>
        TQFile f("/sys/class/rfkill/" + d[i] + "/name");
        TQString content;
        if (f.exists() && f.open(IO_ReadOnly))
        {
            TQTextStream stream(&f);
            content = stream.readLine();
            f.close();
        }
        else
        {
            continue;
        }
        if (content.startsWith(device))
        {
            TQFile f("/sys/class/rfkill/" + d[i] + "/index");
            if (f.exists() && f.open(IO_ReadOnly))
            {
                TQTextStream stream(&f);
                hcidx = stream.readLine().toUInt();
                f.close();
            }
            break;
        }
    }

    if (hcidx < 0)
    {
        // error handling
        tqDebug(i18n("Index for the device %1 not found").arg(device));
        return;
    }

    struct rfkill_event event = { 0 };

    TQFile file("/dev/rfkill");
    if (!file.open(IO_ReadWrite))
    {
        tqDebug(i18n("Failed to open %1").arg(file.name()));
        return;
    }

    event.idx = hcidx;
    event.op = RFKILL_OP_CHANGE;
    if (state)
        event.soft = 0;
    else
        event.soft = 1;

    tqDebug(i18n("Bluetooth device %1 switches: idx(%2), soft(%3).").arg(device).arg(event.idx).arg(event.soft));

    if (write(file.handle(), &event, sizeof(event)) < 0)
        tqDebug(i18n("Failed to write to %1").arg(file.name()));
    file.close();
}

TQString AdapterImpl::getPath()
{
    return TQString(m_baseProxy->path());
}

void AdapterImpl::slotSetAlias(const TQString& alias)
{
    TQT_DBusError dbuserror;
    setAlias(alias, dbuserror);
    if (dbuserror.isValid())
        tqDebug(i18n("AdapterImpl::slotSetAlias(%1) failed: %2").arg(alias).arg(dbuserror.message()));
}

void AdapterImpl::slotSetTimeout(int timeout)
{
    TQT_DBusError dbuserror;
    setDiscoverableTimeout(timeout, dbuserror);
    if (dbuserror.isValid())
        tqDebug(i18n("AdapterImpl::slotSetTimeout(%1) failed: %2").arg(timeout).arg(dbuserror.message()));
}

} // namespace TDEBluetooth

#include "adapterImpl.moc"
// End of File
