package  com.manageengine.plugin.jira
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.adventnet.passtrix.api.RemotePasswordReset;
import com.adventnet.passtrix.utils.ResourceDetails;

public  class JiraResetImplementation  implements RemotePasswordReset {
    private  static Logger log = Logger.getLogger(ServiceNowImpl.class.getName());
    String errorMessage =  "";
    String cookie =  null;
    @Override
    public  boolean changeRemotePassword(Properties  resetProps)  throws Exception {
        ResourceDetails rDetails = (ResourceDetails) resetProps.get("RESOURCEDETAILS");
        String jiraServerUrl = rDetails.getResourceURL();
        String newPassword = (String) resetProps.get("NEWPASSWORD");
        String userName = (String) resetProps.get("ACCOUNTNAME");
        String password = (String) resetProps.get("OLDPASSWORD");

        boolean isPasswordChanged =  false;

        if (openConnection(jiraServerUrl)) {
            if (loginToJiraServerUserAccount(userName, password, jiraServerUrl)) {
                isPasswordChanged = changeJiraServerUserAccountPassword(newPassword, password, jiraServerUrl);
                logoutFromJiraServerUserAccount(jiraServerUrl);

            }
        }
        return isPasswordChanged;
    }

    @Override
    public String getErrorMessage()  throws Exception {
        return  this.errorMessage;
    }

    @Override
    public  boolean isDeviceAvailable(Properties verifyProps)  throws Exception {
        ResourceDetails rDetails = (ResourceDetails) verifyProps.get("RESOURCEDETAILS");
        String jiraServerUrl = rDetails.getResourceURL();
        return openConnection(jiraServerUrl);
    }

    @Override
    public  boolean verifyRemotePassword(Properties verifyProps)  throws Exception {
        boolean isPasswordInSync =  false;
        ResourceDetails rDetails = (ResourceDetails) verifyProps.get("RESOURCEDETAILS");
        String userName = (String) verifyProps.get("ACCOUNTNAME");
        String password = (String) verifyProps.get("OLDPASSWORD");
        String jiraServerUrl = rDetails.getResourceURL();
        if (openConnection(jiraServerUrl)) {
            isPasswordInSync = loginToJiraServerUserAccount(userName, password, jiraServerUrl);
            if (isPasswordInSync) {
                logoutFromJiraServerUserAccount(jiraServerUrl);
            }
        }
        return isPasswordInSync;
    }

    private  boolean openConnection(String jiraServerUrl) {
        try {
            URL  connectionUrl =  new URL(jiraServerUrl);
            HttpURLConnection connection =  null;
            HttpURLConnection.setFollowRedirects(false);

            connection = (HttpURLConnection)  connectionUrl.openConnection();
            connection.setRequestMethod("HEAD");
            connection.setDoOutput(true);
            connection.setConnectTimeout(10000);

            if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                return  true;
            } 
            else {
                this.errorMessage =  "Not able to connect to Jira Server";
                return  false;
            }
        } 
        catch (UnknownHostException e) {
            this.errorMessage =  "Not able to connect to Jira Server";
            return  false;
        } 
        catch (SocketTimeoutException e) {
            return  true;
        } 
        catch (Exception e) {
            this.errorMessage =  "Not able to connect to Jira Server";
            return  false;
        }
    }

    private  boolean loginToJiraServerUserAccount(String userName, String password, String jiraServerUrl) {
        boolean isLoginSuccessful =  false;
        String loginUrl = jiraServerUrl +  "/rest/auth/1/session"; 
        try {
            URL  connectionUrl =  new URL(loginUrl); 
            HttpURLConnection connection = (HttpURLConnection)  connectionUrl.openConnection();
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Accept-Charset",  "UTF-8");
            connection.setDoOutput(true);  
            connection.setRequestProperty( "Content-Type",  "application/json"); 
            OutputStream os = connection.getOutputStream();
            OutputStreamWriter osw =  new OutputStreamWriter(os,  "UTF-8");    
            String credentialjson =  "{\"username\":\"" + userName + "\",\"password\":\"" + password + "\"}";
            osw.write(credentialjson);
            osw.flush();
            osw.close();
            os.close();  
            connection.connect();

            int responseCode = connection.getResponseCode();
            cookie = connection.getHeaderField("Set-Cookie");
            if (responseCode == 200)  {
                return  true;
            } else  if (responseCode == 401) {
                this.errorMessage =  "Authentication error";
            } else {
                this.errorMessage =  "Unknown error occurred";
            }
        } catch (Exception e) {
            log.log(Level.SEVERE,  "Exception occurred while login to JiraServer", e);
        }
        return isLoginSuccessful;
    }

    private  boolean changeJiraServerUserAccountPassword(String newPassword, String password, String jiraServerUrl) {
        boolean isChangePasswordSuccessful =  false;
        String changePwdUrl = jiraServerUrl +  "/rest/api/2/myself/password"; 
        try {
            URL  connectionUrl =  new URL(changePwdUrl); 
            HttpURLConnection connection = (HttpURLConnection)  connectionUrl.openConnection();
            connection.setRequestMethod("PUT");
            connection.setRequestProperty("Accept-Charset",  "UTF-8");
            connection.setDoOutput(true);  
            connection.setRequestProperty( "Content-Type",  "application/json");  //NO I18N
            if (cookie !=  null) {
                connection.setRequestProperty("Cookie", cookie); 
            }

            OutputStream os = connection.getOutputStream();
            OutputStreamWriter osw =  new OutputStreamWriter(os,  "UTF-8");    
            String credentialjson =  "{\"password\":\"" + newPassword + "\",\"currentPassword\":\"" + password + "\"}";
            osw.write(credentialjson);
            osw.flush();
            osw.close();
            os.close();  
            connection.connect();

            int responseCode = connection.getResponseCode();
            if (responseCode == 204) {
                return  true;
            } else  if (responseCode == 401) {
                this.errorMessage =  "Authentication error: Check the admin account password";
            } else  if (responseCode == 400) {
                this.errorMessage =  "Check the new password";
            } else  if (responseCode == 403) {
                this.errorMessage =  "Admin user doesn't have permission to change the password";
            } else  if (responseCode == 404) {
                this.errorMessage =  "User doesn't exist";
            } else {
                this.errorMessage =  "Unknown error occurred";
            }
        } catch (Exception e) {
            log.log(Level.SEVERE,  "Exception occurred while login to JiraServer", e);
        }
        return isChangePasswordSuccessful;
    }

    private  boolean logoutFromJiraServerUserAccount(String jiraServerUrl) {
        boolean isLogoutSuccessful =  false;
        String logoutUrl = jiraServerUrl +  "/rest/auth/1/session"; 
        try {
            URL  connectionUrl =  new URL(logoutUrl); 
            HttpURLConnection connection = (HttpURLConnection)  connectionUrl.openConnection();
            connection.setRequestMethod("DELETE");
            connection.setRequestProperty("Accept-Charset",  "UTF-8");
            connection.setDoOutput(true);  
            connection.setRequestProperty( "Content-Type",  "application/json"); 
            if (cookie !=  null) {
                connection.setRequestProperty("Cookie", cookie); 
            }

            connection.connect();

            int responseCode = connection.getResponseCode();
            if (responseCode == 204)  {
                return  true;
            } else  if (responseCode == 401) {
                log.log(Level.SEVERE,  "Error occurred while logout from JiraServer    -  Authentication error");
            } else {
                log.log(Level.SEVERE,  "Unknown error occurred");;
            }
        } catch (Exception e) {
            log.log(Level.SEVERE,  "Exception occurred while login to JiraServer", e);
        }
        return isLogoutSuccessful;
    }
}