import logging
from xattr import getxattr, removexattr, setxattr
from certidude import push
from certidude.decorators import serialize, csrf_protection
from .utils import AuthorityHandler
from .utils.firewall import login_required, authorize_admin

logger = logging.getLogger(__name__)

class TagResource(AuthorityHandler):
    @serialize
    @login_required
    @authorize_admin
    def on_get(self, req, resp, cn):
        path, buf, cert, signed, expires = self.authority.get_signed(cn)
        tags = []
        try:
            for tag in getxattr(path, "user.xdg.tags").decode("utf-8").split(","):
                if "=" in tag:
                    k, v = tag.split("=", 1)
                else:
                    k, v = "other", tag
                tags.append(dict(id=tag, key=k, value=v))
        except IOError: # No user.xdg.tags attribute
            pass
        return tags


    @csrf_protection
    @login_required
    @authorize_admin
    def on_post(self, req, resp, cn):
        path, buf, cert, signed, expires = self.authority.get_signed(cn)
        key, value = req.get_param("key", required=True), req.get_param("value", required=True)
        try:
            tags = set(getxattr(path, "user.xdg.tags").decode("utf-8").split(","))
        except IOError:
            tags = set()
        if key == "other":
            tags.add(value)
        else:
            tags.add("%s=%s" % (key,value))
        setxattr(path, "user.xdg.tags", ",".join(tags).encode("utf-8"))
        logger.info("Tag %s=%s set for %s by %s" % (key, value, cn, req.context.get("user")))
        push.publish("tag-update", cn)


class TagDetailResource(object):
    def __init__(self, authority):
        self.authority = authority

    @csrf_protection
    @login_required
    @authorize_admin
    def on_put(self, req, resp, cn, tag):
        path, buf, cert, signed, expires = self.authority.get_signed(cn)
        value = req.get_param("value", required=True)
        try:
            tags = set(getxattr(path, "user.xdg.tags").decode("utf-8").split(","))
        except IOError:
            tags = set()
        try:
            tags.remove(tag)
        except KeyError:
            pass
        if "=" in tag:
            tags.add("%s=%s" % (tag.split("=")[0], value))
        else:
            tags.add(value)
        setxattr(path, "user.xdg.tags", ",".join(tags).encode("utf-8"))
        logger.info("Tag %s set to %s for %s by %s" % (tag, value, cn, req.context.get("user")))
        push.publish("tag-update", cn)

    @csrf_protection
    @login_required
    @authorize_admin
    def on_delete(self, req, resp, cn, tag):
        path, buf, cert, signed, expires = self.authority.get_signed(cn)
        tags = set(getxattr(path, "user.xdg.tags").decode("utf-8").split(","))
        tags.remove(tag)
        if not tags:
            removexattr(path, "user.xdg.tags")
        else:
            setxattr(path, "user.xdg.tags", ",".join(tags))
        logger.info("Tag %s removed for %s by %s" % (tag, cn, req.context.get("user")))
        push.publish("tag-update", cn)
