/*
 This file is part of GNUnet.
  (C) 2012, 2013 Christian Grothoff (and other contributing authors)

  GNUnet 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 3, or (at your
  option) any later version.

  GNUnet 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 GNUnet; see the file COPYING.  If not, write to the
  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  Boston, MA 02111-1307, USA.
 */

package org.gnunet.voting;

import com.google.common.base.Strings;
import org.gnunet.identity.Identity;
import org.gnunet.identity.IdentityCallback;
import org.gnunet.util.AbsoluteTime;
import org.gnunet.util.Configuration;
import org.gnunet.util.Program;
import org.gnunet.util.crypto.EcdsaPublicKey;
import org.gnunet.util.getopt.Argument;
import org.gnunet.util.getopt.ArgumentAction;

/**
 * Tool to create group certificates.
 */
public class CertifyGroupTool extends Program {
    @Argument(
            shortname = "e",
            longname = "ego",
            action = ArgumentAction.STORE_STRING,
            argumentName = "EGONAME",
            description = "name of the identity ego to use for signing")
    public String egoName = null;

    @Argument(
            shortname = "m",
            longname = "member",
            action = ArgumentAction.STORE_STRING,
            argumentName = "KEY",
            description = "key to certify membership for")
    String memberPubKeyString;

    @Argument(
            shortname = "g",
            longname = "group",
            action = ArgumentAction.STORE_STRING,
            argumentName = "NAME",
            description = "group to certify membership of key for")
    String groupName;

    @Argument(
            shortname = "x",
            longname = "expire",
            action = ArgumentAction.STORE_STRING,
            argumentName = "DATE",
            description = "expiration date, in local time")
    String expirationDate;


    @Override
    protected String makeHelpText() {
        return "gnunet-ballot-group-certify [OPTIONS]...\n" +
               "Create a certificate attesting group membership for a given key.\n" +
               "The resulting certificate file written to standard output.";
    }

    public static void main(String args[]) {
        CertifyGroupTool tool = new CertifyGroupTool();
        int ret = tool.start(args);
        System.exit(ret);
    }

    private void certify(Identity.Ego ego, EcdsaPublicKey memberPubKey, AbsoluteTime expiration) {
        GroupCert groupCert = GroupCert.create(memberPubKey, groupName, ego.getPrivateKey(),
                ego.getPublicKey(), expiration);
        Configuration cfg = new Configuration();
        groupCert.writeGroupCertConfig(cfg);
        System.out.println(cfg.serialize());
    }

    @Override
    protected void run() {
        if (Strings.isNullOrEmpty(egoName)) {
            System.err.println("no ego name given");
            setReturnValue(1);
            return;
        }
        if (null == memberPubKeyString) {
            System.err.println("no member pubkey given");
            setReturnValue(1);
            return;
        }
        if (Strings.isNullOrEmpty(groupName)) {
            System.err.println("no group identifier given");
            setReturnValue(1);
            return;
        }
        final EcdsaPublicKey memberPubKey = EcdsaPublicKey.fromString(memberPubKeyString);
        if (null == memberPubKey) {
            System.err.println("not a valid pubkey: '" + memberPubKeyString + "'");
            setReturnValue(1);
            return;
        }
        final AbsoluteTime expiration;
        if (null == expirationDate) {
            expiration = AbsoluteTime.FOREVER;
        } else {
            expiration = AbsoluteTime.fromString(expirationDate);
            if (null == expiration) {
                System.err.println("invalid expiration date");
                setReturnValue(1);
                return;
            }
        }
        Identity.lookup(getConfiguration(), egoName, new IdentityCallback() {
            @Override
            public void onEgo(Identity.Ego ego) {
                certify(ego, memberPubKey, expiration);
            }

            @Override
            public void onError(String errorMessage) {
                System.err.println("can't retrieve ego: " + errorMessage);
                setReturnValue(2);
            }
        });
    }
}
