/*
 * Copyright (c) 2009 The openGion Project.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package org.opengion.fukurou.util;

import org.opengion.fukurou.system.OgRuntimeException ;

import java.io.OutputStream;
import java.io.BufferedWriter;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.Proxy;
import java.net.InetSocketAddress;
import java.net.URLEncoder;

/**
 * LineNotify は、Line Notify を利用してLineﾒｯｾｰｼﾞを送信します。
 *
 *　《手順》
 *　　１．https://notify-bot.line.me/ja/　からログインして
 *　　　　マイページから「アクセストークンを発行」をクリック
 *　　２．トークンを設定する。
 *
 * <pre>
 * Usage: java org.opengion.fukurou.util.LineNotify -token アクセストークン -message メッセージ -stickerPackageId 4 -stickerId 614
 * </pre>
 *
 *　《SystemのProxy設定を使用》
 *　java 起動時に、-Djava.net.useSystemProxies=true　を指定する。
 *　プログラム内で設定済みです。
 *
 * @og.rev 7.2.6.2 (2020/07/22) 新規作成
 *
 * @version  7.2
 * @author   Kazuhiko Hasegawa
 * @since    JDK11.0,
 */
public class LineNotify {
	private final String token;
	private final Proxy  proxy;

	private String	stmpPkg ;
	private String	stmpId ;

	/**
	 * アクセストークンを指定した、コンストラクター
	 *
	 * Proxyは、java.net.useSystemProxies=true 設定を使用します。
	 *
	 * @param	token	アクセストークン
	 */
	public LineNotify( final String token ) {
		this.token = token;
		this.proxy = null;

		System.setProperty("java.net.useSystemProxies","true");		// Proxyの自動設定
	}

	/**
	 * アクセストークンを指定した、コンストラクター
	 *
	 * Proxyが、nullか、ゼロ文字列の場合は、Proxy.NO_PROXY を指定します。
	 * そうでない場合は、アドレス:ポート形式で指定します。
	 *
	 *
	 * @param	token	アクセストークン(Line Notifyで取得したID)
	 * @param	proxy	アドレス:ポート形式で指定します。
	 */
	public LineNotify( final String token,final String proxy ) {
		this.token = token;
		if( proxy == null || proxy.isEmpty() ) {
			this.proxy = Proxy.NO_PROXY;
		}
		else {
			final int ad = proxy.indexOf( ':' );
			final String adrs = proxy.substring( 0,ad );
			final int    port = Integer.parseInt( proxy.substring( ad+1 ) );

			this.proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(adrs, port));
		}
	}

	/**
	 * スタンプ（スティッカー）を指定します。
	 *
	 * 指定は、パッケージIDとIDの両方とも必要です。
	 *
	 * @param	stmpPkg stickerPackageIdを指定します。
	 * @param	stmpId  stickerIdを指定します。
	 */
	public void setStamp( final String stmpPkg , final String stmpId ) {
		this.stmpPkg = stmpPkg;
		this.stmpId  = stmpId ;
	}

	/**
	 * メッセージを送信します。
	 *
	 * 送信は、コネクションを毎回disconnectします。
	 *
	 * @param	message 送信するメッセージ
	 */
	public void notify( final String message ) {
		HttpURLConnection connection = null;
		try {
			final URL url = new URL( "https://notify-api.line.me/api/notify" );
			if( proxy == null ) {
				connection = (HttpURLConnection) url.openConnection();
			}
			else {
				connection = (HttpURLConnection) url.openConnection(proxy);
			}
			connection.setDoOutput( true );				// POST可能にする
			connection.setDoInput( true );				// getResponseCode を取得するため
			connection.setRequestMethod( "POST" );
			connection.addRequestProperty( "Authorization", "Bearer " + token );
			connection.setConnectTimeout( 10*1000 );	// 10秒でタイムアウト

			try( OutputStream os = connection.getOutputStream();
				 BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8")) ) {

//				writer.append( "message=" ).append( message );
				writer.append( "message=" ).append( URLEncoder.encode(message, "UTF-8") );
				if( !StringUtil.isNull( stmpPkg,stmpId ) ) {
					writer.append( "&stickerPackageId=" ).append( stmpPkg );
					writer.append( "&stickerId="        ).append( stmpId  );
				}
				writer.flush();

				final int status = connection.getResponseCode();
				if( status != HttpURLConnection.HTTP_OK ) {
					final String errMsg = HttpConnect.code2Message( status );
					throw new OgRuntimeException( errMsg );
				}
			}
		}
		catch( final Throwable th ) {
			throw new OgRuntimeException( th );
		}
		finally {
			if( connection != null ) {
				connection.disconnect();
			}
		}
	}

	/**
	 * サンプル実行用のメインメソッド。
	 *
	 * @param	args	コマンド引数配列。
	 */
	public static void main( final String[] args ) {
		String token   = "XXXX";
		String message = "テスト";
		String stmpPkg = "4";
		String stmpId  = "614";

		for( int i=0; i<args.length; i++ ) {
			if( "-token".equalsIgnoreCase( args[i] ) ) {
				token = args[++i];
			}
			else if( "-message".equalsIgnoreCase( args[i] ) ) {
				message = args[++i];
			}
			else if( "-stickerPackageId".equalsIgnoreCase( args[i] ) ) {
				stmpPkg = args[++i];
			}
			else if( "-stickerId".equalsIgnoreCase( args[i] ) ) {
				stmpId = args[++i];
			}
		}

		final LineNotify lineNotify = new LineNotify( token );
		lineNotify.setStamp( stmpPkg,stmpId );
		lineNotify.notify( message );
	}
}
