package org.wso2.carbon.grant.ntlm;

import org.apache.catalina.Realm;
import org.wso2.carbon.grant.ntlm.utils.SimpleHttpRequest;
import org.wso2.carbon.grant.ntlm.utils.SimpleHttpResponse;
import org.wso2.carbon.grant.ntlm.utils.SimpleRealm;
import waffle.apache.NegotiateAuthenticator;
import waffle.util.Base64;
import waffle.windows.auth.IWindowsCredentialsHandle;
import waffle.windows.auth.impl.WindowsAccountImpl;
import waffle.windows.auth.impl.WindowsCredentialsHandleImpl;
import waffle.windows.auth.impl.WindowsSecurityContextImpl;
import org.apache.axiom.util.base64.Base64Utils;
import org.apache.felix.gogo.command.Base64Encoder;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.axiom.util.base64.Base64Utils;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.wso2.carbon.grant.ntlm.utils.CommandHandler;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

import java.io.IOException;

/**
 * NTLM sample Main class.This class will create a NTLM token and send to the wso2 api manager token end point and will
 * receive an access token.
 */
public class Main {
    static NegotiateAuthenticator _authenticator = null;

    public static void main(String[] args) {

        System.out.println("Started NTLM grant client................");
        CommandHandler.setInputs(args);
        _authenticator = new NegotiateAuthenticator();

        String securityPackage = "Negotiate";
        boolean autoGenerate = CommandHandler.isTokenAutoGenerated();
        String clientToken = "";
        if (autoGenerate) {
            IWindowsCredentialsHandle clientCredentials = null;
            WindowsSecurityContextImpl clientContext = null;
            // client credentials handle
            clientCredentials = WindowsCredentialsHandleImpl.getCurrent(securityPackage);
            clientCredentials.initialize();
            // initial client security context
            clientContext = new WindowsSecurityContextImpl();
            clientContext.setPrincipalName(WindowsAccountImpl.getCurrentUsername());
            System.out.println("username" + WindowsAccountImpl.getCurrentUsername());
            clientContext.setCredentialsHandle(clientCredentials.getHandle());
            clientContext.setSecurityPackage(securityPackage);
            clientContext.initialize(null, null, WindowsAccountImpl.getCurrentUsername());

            clientToken = Base64.encode(clientContext.getToken());
            System.out.println("Generated NTLM token:" + clientToken);
        } else {
            clientToken = CommandHandler.getNTLMToken();
            System.out.println("NTLM token: " + clientToken);
        }
        try {
            Thread.sleep(4000);
            HttpClient httpclient = new DefaultHttpClient();
            byte[] userKey = (CommandHandler.getConsumerKey() + ":" + CommandHandler.getConsumerSecret()).getBytes();
            String encoding = Base64Utils.encode(userKey);
            HttpPost httppost = new HttpPost(CommandHandler.getTokenendpoint());
            httppost.setHeader("Authorization", "Basic " + encoding);
            List<NameValuePair> paramVals = new ArrayList<NameValuePair>();
            paramVals.add(new BasicNameValuePair("grant_type", "iwa:ntlm"));
            paramVals.add(new BasicNameValuePair("windows_token", clientToken));

            System.out.println("executing token API request " + httppost.getRequestLine());
            HttpResponse response = null;
            httppost.setEntity(new UrlEncodedFormEntity(paramVals, "UTF-8"));
            response = httpclient.execute(httppost);
            HttpEntity entity = response.getEntity();
            String responseString = EntityUtils.toString(entity, "UTF-8");
            System.out.println(responseString);
            System.out.println("Completed NTLM grant client................");
            System.exit(0);
        } catch (IOException e) {
            System.out.print("Error has occoured while sending POST request to Gateway " + e.getMessage());
        }
        catch (InterruptedException e) {
            System.out.print("Error has occurred while thread sleep " + e.getMessage());
        }

    }
}
