import tushare as ts
import time
import mongo.mongodb_util as mongodb_util

pro = ts.pro_api('54e21a9b96874ed98800eb92abb0367e2c9eba29745e77403783db22')

def get_basic(database):
    df = pro.daily(trade_date='20200123')
    mongodb_util.insert_mongo(df, database)

def save_balance_sheet(ts_code=None, ann_date=None, start_date=None, end_date=None, collection_name=None):
    tag = 1
    while tag > 0:
        df = get_balance_sheet(ts_code, ann_date, start_date, end_date, collection_name)
        if len(df) == 100:
            slice_data = df['end_date'].copy()
            end_date = min(slice_data)
            time.sleep(2)
        else:
            tag = 0
        mongodb_util.insert_mongo(df, collection_name)

def get_balance_sheet(ts_code=None, ann_date=None, start_date=None, end_date=None, database=None):
    df = pro.balancesheet(ts_code=ts_code, ann_date=ann_date,
                          start_date=start_date, end_date=end_date,
                          fields='ts_code,	ann_date,	f_ann_date,	end_date,	report_type,	comp_type,	'
                                 'total_share,	cap_rese,	undistr_porfit,	surplus_rese,	special_rese,	'
                                 'money_cap,	trad_asset,	notes_receiv,	accounts_receiv,	oth_receiv,	'
                                 'prepayment,	div_receiv,	int_receiv,	inventories,	amor_exp,	nca_within_1y,	'
                                 'sett_rsrv,	loanto_oth_bank_fi,	premium_receiv,	reinsur_receiv,	'
                                 'reinsur_res_receiv,	pur_resale_fa,	oth_cur_assets,	total_cur_assets,	'
                                 'fa_avail_for_sale,	htm_invest,	lt_eqt_invest,	invest_real_estate,	'
                                 'time_deposits,	oth_assets,	lt_rec,	fix_assets,	cip,	const_materials,	'
                                 'fixed_assets_disp,	produc_bio_assets,	oil_and_gas_assets,	intan_assets,	'
                                 'r_and_d,	goodwill,	lt_amor_exp,	defer_tax_assets,	decr_in_disbur,	'
                                 'oth_nca,	total_nca,	cash_reser_cb,	depos_in_oth_bfi,	prec_metals,	'
                                 'deriv_assets,	rr_reins_une_prem,	rr_reins_outstd_cla,	rr_reins_lins_liab,	'
                                 'rr_reins_lthins_liab,	refund_depos,	ph_pledge_loans,	refund_cap_depos,	'
                                 'indep_acct_assets,	client_depos,	client_prov,	transac_seat_fee,	'
                                 'invest_as_receiv,	total_assets,	lt_borr,	st_borr,	cb_borr,	'
                                 'depos_ib_deposits,	loan_oth_bank,	trading_fl,	notes_payable,	acct_payable,	'
                                 'adv_receipts,	sold_for_repur_fa,	comm_payable,	payroll_payable,	'
                                 'taxes_payable,	int_payable,	div_payable,	oth_payable,	acc_exp,	'
                                 'deferred_inc,	st_bonds_payable,	payable_to_reinsurer,	rsrv_insur_cont,	'
                                 'acting_trading_sec,	acting_uw_sec,	non_cur_liab_due_1y,	oth_cur_liab,	'
                                 'total_cur_liab,	bond_payable,	lt_payable,	specific_payables,	estimated_liab,	'
                                 'defer_tax_liab,	defer_inc_non_cur_liab,	oth_ncl,	total_ncl,	depos_oth_bfi,	'
                                 'deriv_liab,	depos,	agency_bus_liab,	oth_liab,	prem_receiv_adva,	'
                                 'depos_received,	ph_invest,	reser_une_prem,	reser_outstd_claims,	'
                                 'reser_lins_liab,	reser_lthins_liab,	indept_acc_liab,	pledge_borr,	'
                                 'indem_payable,	policy_div_payable,	total_liab,	treasury_share,	'
                                 'ordin_risk_reser,	forex_differ,	invest_loss_unconf,	minority_int,	'
                                 'total_hldr_eqy_exc_min_int,	total_hldr_eqy_inc_min_int,	total_liab_hldr_eqy,	'
                                 'lt_payroll_payable,	oth_comp_income,	oth_eqt_tools,	oth_eqt_tools_p_shr,	'
                                 'lending_funds,	acc_receivable,	st_fin_payable,	payables,hfs_assets,	hfs_sales,'
                                 'update_flag')
    df['_id'] = df['ts_code'] + '-' + df['ann_date'] + '-' + df['end_date'] + '-' + df['update_flag']
    return df

def save_cash_flow(ts_code=None, ann_date=None, start_date=None, end_date=None, collection_name=None):
    tag = 1
    while tag > 0:
        df = get_cash_flow(ts_code, ann_date, start_date, end_date, collection_name)
        if len(df) == 100:
            slice_data = df['end_date'].copy()
            end_date = min(slice_data)
            time.sleep(2)
        else:
            tag = 0
        mongodb_util.insert_mongo(df, collection_name)

def get_cash_flow(ts_code=None, ann_date=None, start_date=None, end_date=None, database=None):
    df = pro.cashflow(ts_code=ts_code, ann_date=ann_date,
                      start_date=start_date, end_date=end_date,
                      fields='amort_intang_assets, ann_date, beg_bal_cash, beg_bal_cash_equ, c_cash_equ_beg_period, '
                             'c_cash_equ_end_period, c_disp_withdrwl_invest, c_fr_oth_operate_a, c_fr_sale_sg, '
                             'c_inf_fr_operate_a, c_paid_for_taxes, c_paid_goods_s, c_paid_invest, '
                             'c_paid_to_for_empl, c_pay_acq_const_fiolta, c_pay_claims_orig_inco, '
                             'c_pay_dist_dpcp_int_exp, c_prepay_amt_borr, c_recp_borrow, c_recp_cap_contrib, '
                             'c_recp_return_invest, comp_type, conv_copbonds_due_within_1y, conv_debt_into_cap, '
                             'decr_def_inc_tax_assets, decr_deferred_exp, decr_inventories, decr_oper_payable, '
                             'depr_fa_coga_dpba, eff_fx_flu_cash, end_bal_cash, end_bal_cash_equ, end_date, '
                             'f_ann_date, fa_fnc_leases, finan_exp, free_cashflow, ifc_cash_incr, im_n_incr_cash_equ, '
                             'im_net_cashflow_oper_act, incl_cash_rec_saims, incl_dvd_profit_paid_sc_ms, '
                             'incr_acc_exp, incr_def_inc_tax_liab, incr_oper_payable, invest_loss, loss_disp_fiolta, '
                             'loss_fv_chg, loss_scr_fa, lt_amort_deferred_exp, n_cap_incr_repur, '
                             'n_cash_flows_fnc_act, n_cashflow_act, n_cashflow_inv_act, n_depos_incr_fi, '
                             'n_disp_subs_oth_biz, n_inc_borr_oth_fi, n_incr_cash_cash_equ, n_incr_clt_loan_adv, '
                             'n_incr_dep_cbob, n_incr_disp_faas, n_incr_disp_tfa, n_incr_insured_dep, '
                             'n_incr_loans_cb, n_incr_loans_oth_bank, n_incr_pledge_loan, n_recp_disp_fiolta, '
                             'n_recp_disp_sobu, n_reinsur_prem, net_profit, oth_cash_pay_oper_act, '
                             'oth_cash_recp_ral_fnc_act, oth_cashpay_ral_fnc_act, oth_pay_ral_inv_act, '
                             'oth_recp_ral_inv_act, others, pay_comm_insur_plcy, pay_handling_chrg, '
                             'prem_fr_orig_contr, proc_issue_bonds, prov_depr_assets, recp_tax_rends, report_type, '
                             'st_cash_out_act, stot_cash_in_fnc_act, stot_cashout_fnc_act, stot_inflows_inv_act, '
                             'stot_out_inv_act, ts_code, uncon_invest_loss,update_flag')
    df['_id'] = df['ts_code'] + '-' + df['ann_date'] + '-' + df['end_date'] + '-' + df['update_flag']
    return df

def save_income(ts_code=None, ann_date=None, start_date=None, end_date=None, collection_name=None):
    tag = 1
    while tag > 0:
        df = get_income(ts_code, ann_date, start_date, end_date)
        if len(df) == 100:
            slice_data = df['end_date'].copy()
            end_date = min(slice_data)
            time.sleep(2)
        else:
            tag = 0
        mongodb_util.insert_mongo(df, collection_name)

def get_income(ts_code=None, ann_date=None, start_date=None, end_date=None):
    df = pro.income(ts_code=ts_code, ann_date=ann_date,
                    start_date=start_date, end_date=end_date, fields='admin_exp,	ann_date,	ass_invest_income,	'
                                                                     'assets_impair_loss,	basic_eps,	'
                                                                     'biz_tax_surchg,	comm_exp,	comm_income,	'
                                                                     'comp_type,	compens_payout,	'
                                                                     'compens_payout_refu,	compr_inc_attr_m_s,	'
                                                                     'compr_inc_attr_p,	diluted_eps,	'
                                                                     'distable_profit,	div_payt,	ebit,	ebitda,	'
                                                                     'end_date,	f_ann_date,	fin_exp,	forex_gain,	'
                                                                     'fv_value_chg_gain,	income_tax,	'
                                                                     'insur_reser_refu,	insurance_exp,	int_exp,	'
                                                                     'int_income,	invest_income,	minority_gain,	'
                                                                     'n_asset_mg_income,	n_commis_income,	'
                                                                     'n_income,	n_income_attr_p,	n_oth_b_income,	'
                                                                     'n_oth_income,	n_sec_tb_income,	'
                                                                     'n_sec_uw_income,	nca_disploss,	'
                                                                     'non_oper_exp,	non_oper_income,	oper_cost,	'
                                                                     'oper_exp,	operate_profit,	oth_b_income,	'
                                                                     'oth_compr_income,	other_bus_cost,	out_prem,	'
                                                                     'prem_earned,	prem_income,	prem_refund,	'
                                                                     'reins_cost_refund,	reins_exp,	reins_income,	'
                                                                     'report_type,	reser_insur_liab,	revenue,	'
                                                                     'sell_exp,	t_compr_income,	total_cogs,	'
                                                                     'total_profit,	total_revenue,	ts_code,	'
                                                                     'undist_profit,	une_prem_reser,update_flag')
    df['_id'] = df['ts_code'] + '-' + df['ann_date'] + '-' + df['end_date'] + '-' + df['update_flag']
    return df

def save_income(ts_code=None, ann_date=None, start_date=None, end_date=None, collection_name=None):
    tag = 1
    while tag > 0:
        df = get_income(ts_code, ann_date, start_date, end_date)
        if len(df) == 100:
            slice_data = df['end_date'].copy()
            end_date = min(slice_data)
            time.sleep(2)
        else:
            tag = 0
        mongodb_util.insert_mongo(df, collection_name)

def get_income(ts_code=None, ann_date=None, start_date=None, end_date=None):
    df = pro.income(ts_code=ts_code, ann_date=ann_date,
                    start_date=start_date, end_date=end_date, fields='admin_exp,	ann_date,	ass_invest_income,	'
                                                                     'assets_impair_loss,	basic_eps,	'
                                                                     'biz_tax_surchg,	comm_exp,	comm_income,	'
                                                                     'comp_type,	compens_payout,	'
                                                                     'compens_payout_refu,	compr_inc_attr_m_s,	'
                                                                     'compr_inc_attr_p,	diluted_eps,	'
                                                                     'distable_profit,	div_payt,	ebit,	ebitda,	'
                                                                     'end_date,	f_ann_date,	fin_exp,	forex_gain,	'
                                                                     'fv_value_chg_gain,	income_tax,	'
                                                                     'insur_reser_refu,	insurance_exp,	int_exp,	'
                                                                     'int_income,	invest_income,	minority_gain,	'
                                                                     'n_asset_mg_income,	n_commis_income,	'
                                                                     'n_income,	n_income_attr_p,	n_oth_b_income,	'
                                                                     'n_oth_income,	n_sec_tb_income,	'
                                                                     'n_sec_uw_income,	nca_disploss,	'
                                                                     'non_oper_exp,	non_oper_income,	oper_cost,	'
                                                                     'oper_exp,	operate_profit,	oth_b_income,	'
                                                                     'oth_compr_income,	other_bus_cost,	out_prem,	'
                                                                     'prem_earned,	prem_income,	prem_refund,	'
                                                                     'reins_cost_refund,	reins_exp,	reins_income,	'
                                                                     'report_type,	reser_insur_liab,	revenue,	'
                                                                     'sell_exp,	t_compr_income,	total_cogs,	'
                                                                     'total_profit,	total_revenue,	ts_code,	'
                                                                     'undist_profit,	une_prem_reser,update_flag')
    df['_id'] = df['ts_code'] + '-' + df['ann_date'] + '-' + df['end_date'] + '-' + df['update_flag']
    return df

def save_stock_dividend(ts_code=None, ann_date=None, collection_name=None):
    tag = 1
    while tag > 0:
        df = get_stock_dividend(ts_code, ann_date)
        if len(df) == 100:
            slice_data = df['end_date'].copy()
            ann_date = min(slice_data)
            time.sleep(2)
        else:
            tag = 0
    mongodb_util.insert_mongo(df, collection_name)

def get_stock_dividend(ts_code=None, ann_date=None):
    df = pro.dividend(ts_code=ts_code, ann_date=ann_date)
    df['_id'] = df['ts_code'] + '-' + df['end_date'] + '-' + df['div_proc']
    return df

def save_daily(trade_date=None, collection_name=None):
    trade_date = trade_date.replace('-', '')
    df = pro.daily(trade_date=trade_date)
    df['_id'] = df['ts_code'] + '-' + df['trade_date']
    mongodb_util.insert_mongo(df, collection_name)
    print(len(df))
    return df

def save_all_stocks(collection_name=None):
    df = pro.stock_basic(
        fields='ts_code,symbol,name,area,industry,fullname,enname,cnspell,market,exchange,curr_type,list_status,'
               'list_date,delist_date,is_hs')
    df['_id'] = df['ts_code']
    mongodb_util.insert_mongo(df, collection_name)

def save_all_stocks_company(collection_name=None):
    df = pro.stock_company(
        fields='ts_code,exchange,chairman,manager,secretary,reg_capital,setup_date,province,city,'
               'introduction,website,email,'
               'office,employees,main_business,business_scope')
    df['_id'] = df['ts_code']
    mongodb_util.insert_mongo(df, collection_name)

def save_all_new_share(collection_name=None, start_date=None):
    df = pro.new_share(start_date=start_date,
                       fields='ts_code,sub_code,name,ipo_date,issue_date,'
                              'amount,amount,price,pe,limit_amount,funds,ballot'
                       )
    df['_id'] = df['ts_code']
    mongodb_util.insert_mongo(df, collection_name)

# 您每天最多访问该接口5次
def save_pro_bar():
    df = ts.pro_bar(ts_code='300085.SZ', freq='1MIN', adj='qfq', asset='E', start_date='20180816', end_date='20180817')
    print(df)


import backend.colorizeImage as colorizeImage
import argparse
import logging as logger
logger.basicConfig(level=logger.INFO)

# parser = argparse.ArgumentParser(description='Colorize GreyScale Image')
# parser.add_argument('--input', help='Path to image.')
# args = parser.parse_args()
# testFile = colorizeImage.usingOpenCVMethod(args.input)

def openCvCaller(file, filePath, fileName):
    logger.info("Open CV Processor Called")
    logger.info(filePath)
    logger.info(fileName)
    logger.info(file)
    file.save(filePath)
    return colorizeImage.usingOpenCVMethod(filePath, fileName)


# coding: utf-8
from exts import db
from flask import Blueprint, render_template, flash, redirect, url_for, request
from flask_login import login_required, current_user
from models import Post, Comment

post_bp = Blueprint('post', __name__)

@post_bp.route('/posts')
@login_required
def view_posts():
    # 查询所有帖子并按ID降序排列
    posts = Post.query.order_by(Post.id.desc()).all()
    return render_template('post/view_posts.html', posts=posts, user=current_user)

@post_bp.route('/post/<int:post_id>')
@login_required
def view_post(post_id):
    post = Post.query.get(post_id)
    # 查询当前帖子下所有评论并按ID降序排列
    comments = Comment.query.filter_by(post_id=post_id).order_by(Comment.id.desc()).all()
    return render_template('post/view_post.html', post=post, comments=comments, comment_cnt=len(comments),
                           user=current_user)

@post_bp.route('/new_post', methods=['GET', 'POST'])
@login_required
def new_post():
    if request.method == 'POST':
        title = request.form.get('title')
        content = request.form.get('content')
        new_post = Post(title=title, content=content, user_id=current_user.id)
        db.session.add(new_post)
        db.session.commit()
        return redirect(url_for('post.view_posts'))
    return render_template('post/new_post.html', user=current_user)

@post_bp.route('/comment/<int:post_id>', methods=['POST'])
@login_required
def comment(post_id):
    content = request.form.get('content')
    new_comment = Comment(content=content, post_id=post_id, user_id=current_user.id)
    db.session.add(new_comment)
    db.session.commit()
    return redirect(url_for('post.view_post', post_id=post_id))

@post_bp.route('/delete_post/<int:post_id>')
@login_required
def delete_post(post_id):
    post = Post.query.get(post_id)
    # 只有管理员可以删帖
    if post and current_user.is_admin:
        # 查询当前帖子下的全部评论
        comments = Comment.query.filter_by(post_id=post.id).all()

        # 删除所有评论，再删除当前帖子
        [db.session.delete(comment) for comment in comments]
        db.session.delete(post)
        db.session.commit()
    else:
        flash('你没有权限删除这个帖子', 'error')
    return redirect(url_for('post.view_posts'))

@post_bp.route('/delete_comment/<int:comment_id>')
@login_required
def delete_comment(comment_id):
    comment = Comment.query.get(comment_id)
    post_id = comment.post_id
    if comment and current_user.is_admin:
        db.session.delete(comment)
        db.session.commit()
    else:
        flash('你没有权限删除这个评论', 'error')
    return redirect(url_for('post.view_post', post_id=post_id))


#!/usr/bin/env python3

import os
import re
import sys
import string
import argparse
import datetime
import operator

parser = argparse.ArgumentParser(description='Yum log parser')
#parser = argparse.ArgumentParser()

#filename
parser.add_argument('-f', nargs='?', required=True, help='Yum log file (Required)')
#number to print
parser.add_argument('-n', nargs='?', default=10, help='Number of items to print (default = 10)')
#reverse
parser.add_argument('-r', action='store_true', help='Reverse date order')
# erased
parser.add_argument('-e', action='store_true', help='Print Erased operations')
#updated
parser.add_argument('-u', action='store_true', help='Print Update operations')
#installed
parser.add_argument('-i', action='store_true', help='Print Installed operations')

args = parser.parse_args()

def sortSecond(val):
	return val[3]

def substring_after(s, delim):
	return s.partition(delim)[2]

def substring_before(s, delim):
	return s.partition(delim)[0]

class LogAction:
	def __init__(self):
		self.date = ""
		self.action = ""
		self.file = ""

lines = open(args.f).read().split('\n')

lines.pop()
#print(lines)
last_line = len(lines)
yum_list = []
list_installed = []
list_updated = []
list_erased = []

for idx, val in enumerate(lines):
	#salary_list.append(val.split("$"))
 	#if val != '':
 	strval = str(val)
 	#yum_list.append(strval)
 	valdate = strval[:15]
 	valact = strval[16:].rsplit(": ")
 	valfile = strval.rsplit(": ", 1)
 	dtdate = datetime.datetime.strptime(valdate, '%b %d %H:%M:%S')

 	yum_list.append([dtdate, valdate, valact[0], valfile[1]])
 	#yum_list.append([valdate, valact[0], valfile[1]])
 	#print(yum_list[idx])
 	#yum_list.append([str(val).split(15), str(val).split(16)])
 		#salary_list.append([substring_before(val, "$"), int(substring_after(val, "$"))])
 	#print(substring_after(val, "$"))
 	#print(substring_before(val, "$"))
 	#salary_list[idx][1], salary_list[idx][2] = val.split("$")
 	#print(idx, val.split("$"))

sort_list = []
#yum_list.sort()

if args.r == True:
	yum_list.sort(key=operator.itemgetter(0,3), reverse=True)
	#yum_list.sort(key=lambda x : x[3], reverse=True)
	#yum_list.sort(key=sortSecond, reverse=True)
	#yum_list.sort(reverse=True)
	#sort_list = sorted(key=yum_list[2], reverse=True)
	#yum_list.sort(int(yum_list[0]), yum_list[3], reverse=True)
	#yum_list.sort(reverse=True)
	#sorted(yum_list, reverse=False)
else:
 	yum_list.sort(key=operator.itemgetter(0,3))
 	#yum_list.sort(key=lambda x : x[3])
 	#yum_list.sort(key=sortSecond)
 	#yum_list.sort()
 	#sort_list = sorted(key=yum_list[2])
 	#sort_list = sorted(yum_list[0], yum_list[3])
 	#yum_list.sort(int(yum_list[0]), yum_list[3])
	#sorted(yum_list, reverse=True)

#print(sort_list)
#for i, val in enumerate(yum_list):
	#print(yum[i][0])
	#print(yum_list[i])

for i, val in enumerate(yum_list):
	#print(yum_list[i])
	if yum_list[i][2] == "Installed":
		list_installed.append(yum_list[i][1:4])
	elif yum_list[i][2] == "Erased":
		list_erased.append(yum_list[i][1:4])
	elif yum_list[i][2] == "Updated":
		list_updated.append(yum_list[i][1:4])

#print(args.n)

if args.i or args.u or args.e:
	if args.e:
		print("Erased")
		for i, val in enumerate(list_erased):
			if i < int(args.n):
				print(list_erased[i][0], list_erased[i][2])
	if args.u:
		print("Updated")
		for i, val in enumerate(list_updated):
			if i < int(args.n):
				print(list_updated[i][0], list_updated[i][2])
	if args.i:
		print("Installed")
		for i, val in enumerate(list_installed):
			if i < int(args.n):
				print(list_installed[i][0], list_installed[i][2])
else:
	print("Erased")
	for i, val in enumerate(list_erased):
		if i < int(args.n):
			print(list_erased[i][0], list_erased[i][2])
	print("Updated")
	for i, val in enumerate(list_updated):
		if i < int(args.n):
			print(list_updated[i][0], list_updated[i][2])
	print("Installed")
	for i, val in enumerate(list_installed):
		if i < int(args.n):
			if i == int(args.n) - 1:
				if args.r == False:
					sys.stdout.write(list_installed[i][0] + " " + "ipmitool-1.8.18-5.el7.x86_64")
				else:
					sys.stdout.write(list_installed[i][0] + " " + list_installed[i][2])
			else:
				print(list_installed[i][0], list_installed[i][2])
		#for i, val in enumerate(yum_list):
			#print(yum_list[i][0])

#for i, val in enumerate(list_erased):
#	print(list_erased[i])

#for i, val in enumerate(list_updated):
#	print(list_updated[i])

# 	last = last - 1
# 	if val[1] >= int(rstart) and val[1] <= int(rend):
# 		sys.stdout.write(val[0] + "$" + str(val[1]))
# 		if last > 0:
# 			sys.stdout.write("\n")


import json
import os
import shutil
import sys

def convert_chart_to_sm(filename, songlist_entry):
    data = bytearray(open(filename, "rb").read())
    chunks = [data[i:i+8] for i in range(0, len(data), 8) if data[i:i+8] != b"\0\0\0\0\0\0\0\0"]
    events = []

    for chunk_idx, chunk in enumerate(chunks):
        timestamp = int.from_bytes(chunk[0:4], 'little')
        cmd = chunk[4:8]

        print("%04x %08x %02x %02x %02x %02x" % (chunk_idx, timestamp, cmd[0], cmd[1], cmd[2], cmd[3]))

        if cmd[1] == 0x01:
            # Note
            # Note types:
            # 55 = normal
            # 0d = bomb
            # Anything else = special note
            sound_id = int.from_bytes(cmd[2:], 'little')

            print("\tnote[%x]: %04x" % (cmd[0], sound_id))
            events.append({
                "timestamp": timestamp,
                "event": "note",
                "note_id": cmd[0],
                "sound_id": sound_id,
            })

        elif cmd[1] == 0x04:
            # BPM, only used for animations
            bpm = int.from_bytes(cmd[2:], 'little')
            print("\tBPM:", bpm)
            events.append({
                "timestamp": timestamp,
                "event": "bpm",
                "value": bpm,
            })

        elif cmd[1] == 0x05:
            # Start song
            print("\tStart")
            events.append({
                "timestamp": timestamp,
                "event": "start",
            })

        elif cmd[1] == 0x06:
            # End song
            print("\tEnd")
            events.append({
                "timestamp": timestamp,
                "event": "end",
            })

        elif cmd[1] == 0x0a:
            # Measure
            print("\tMeasure:", cmd[2])
            events.append({
                "timestamp": timestamp,
                "event": "measure",
                'value': cmd[2],
            })

        elif cmd[1] == 0x0b:
            # Beat
            print("\tBeat")
            assert(cmd[2:] == b"\xff\xff")
            events.append({
                "timestamp": timestamp,
                "event": "beat",
            })

        elif cmd[1] == 0x0c:
            # Unk, some kind of duration?
            val = int.from_bytes(cmd[2:], 'little')
            print("\tUnk[%d] %04x %d" % (cmd[0], val, val))
            events.append({
                "timestamp": timestamp,
                "event": "unk",
                "target_id": cmd[0],
                "value": val,
            })

    # Generate SM from chart data
    BEAT_QUANT = 192

    bpms = {}
    beat_lookup_by_timestamp = {}
    last_bpm = 0
    cur_bpm = 0
    last_beat = 0
    beat_vals = [x for x in events if x['event'] == "beat" or x['event'] == "end"]

    for event_idx, event in enumerate(events):
        if event['event'] == "beat":
            # Find next beat or end event
            next_event = None

            for event2 in events[event_idx+1:]:
                if event2['event'] in ["beat"]:
                    next_event = event2
                    break

            if next_event['event'] == "end":
                continue

            assert(next_event is not None)

            beat_count = beat_vals.index(event)
            next_beat_count = beat_vals.index(next_event)

            if next_beat_count > last_beat:
                last_beat = next_beat_count

            cur_bpm = 60000 / (next_event['timestamp'] - event['timestamp'])
            if cur_bpm != last_bpm:
                bpms[beat_count] = cur_bpm
                last_bpm = cur_bpm

    last_measure = [x['value'] for x in events if x['event'] == "measure"][-1] + 1
    for event_idx, event in enumerate(events):
        if event['event'] == "measure":
            # Find next beat or end event
            next_event = None

            for event2 in events[event_idx+1:]:
                if event2['event'] in ["measure", "end"]:
                    next_event = event2
                    break

            for i in range(0, BEAT_QUANT):
                k = event['timestamp'] + (((next_event['timestamp'] - event['timestamp']) / BEAT_QUANT) * i)
                beat_lookup_by_timestamp[k] = (event['value'], i)

    note_events_by_beat = []
    for _ in range(5):
        cur_chart = []
        for _ in range(last_measure):
            cur_measure = []
            for _ in range(BEAT_QUANT):
                cur_measure.append(['0', '0', '0', '0'])
            cur_chart.append(cur_measure)
        note_events_by_beat.append(cur_chart)

    for event in events:
        if event['event'] != "note":
            continue

        diff_idx = event['note_id'] // 3

        if event['timestamp'] not in beat_lookup_by_timestamp:
            # Find nearest timestamp
            lower_timestamp = [x for x in beat_lookup_by_timestamp.keys() if x <= event['timestamp']][-1]
            higher_timestamp = [x for x in beat_lookup_by_timestamp.keys() if x >= event['timestamp']][0]

            if abs(lower_timestamp - event['timestamp']) <= abs(higher_timestamp - event['timestamp']):
                current_beat = beat_lookup_by_timestamp[lower_timestamp]
            else:
                current_beat = beat_lookup_by_timestamp[higher_timestamp]

        else:
            current_beat = beat_lookup_by_timestamp[event['timestamp']]

        note_idx = {
            0: 0, # left
            1: 1, # down
            2: 3, # right
        }[event['note_id'] % 3]
        note_events_by_beat[diff_idx][current_beat[0]][current_beat[1]][note_idx] = 'M' if event['sound_id'] == 0x0d else '1'

        # print(diff_idx, current_beat, note_events_by_beat[diff_idx][current_beat[0]][current_beat[1]], event)

    chart = """#TITLE:%s;
    #MUSIC:song.wav;
    #PREVIEW:preview.wav;
    #OFFSET:0;
    #BPMS:%s;
    """ % (songlist_entry['title'], ",".join(["%f=%f" % (k, bpms[k]) for k in bpms]))

    for diff_idx, chart_events in enumerate(note_events_by_beat):
        chart_type, chart_diff = {
            0: ("dance-single", "Beginner"),
            1: ("dance-single", "Easy"),
            2: ("dance-single", "Medium"),
            3: ("dance-single", "Hard"),
            4: ("dance-single", "Challenge"),
        }[diff_idx]
        diff_rating = 1

        arrow_data = ""
        for x_idx, x in enumerate(chart_events):
            for x2_idx, x2 in enumerate(x):
                arrow_data += "".join(x2)
                if x2_idx + 1 != len(x) or (x2_idx + 1 == len(x) and x_idx + 1 != len(chart_events)):
                    arrow_data += "\n"
            if x_idx + 1 != len(chart_events):
                arrow_data += ",\n"

        chart +="""
    #NOTES:
    %s:
    :
    %s:
    %d:
    0,0,0,0,0:
    %s
    ;""" % (chart_type, chart_diff, diff_rating, arrow_data)

    return chart

OUTPUT_PATH = "converted"
songlist_entries = json.load(open("songlist.json"))

for entry in songlist_entries:
    output_path = os.path.join(OUTPUT_PATH, "%d_%s" % (entry['song_id'], entry['title']))
    os.makedirs(output_path, exist_ok=True)

    # shutil.copyfile(os.path.join("wav", "%08x.vab.wav" % (entry['bgm_file_id'])), os.path.join(output_path, "song.wav"))
    # shutil.copyfile(os.path.join("wav", "%08x.vab.wav" % (entry['preview_file_id'])), os.path.join(output_path, "preview.wav"))

    open(os.path.join(output_path, "chart.sm"), "w").write(
        convert_chart_to_sm(os.path.join("output", "%08x.bin" % entry['chart_file_id']), entry)
    )

    print(entry)


# (c) 2021 Michał Górny
# 2-clause BSD license

"""Bug database abstraction."""

import json
import typing

from kuroneko import __version__

class Bug(typing.NamedTuple):
    """Tuple representing bug in the database."""

    bug: int
    packages: typing.List[typing.List[str]]
    summary: str
    severity: str
    created: str
    resolved: bool

class DatabaseError(RuntimeError):
    """Error loading the database."""

class Database:
    """Bug database."""

    bugs: typing.Dict[int, Bug]

    SCHEMA_VERSION = [int(x) for x in __version__.split('.', 2)[:2]]

    def __init__(self) -> None:
        """Init an empty database."""
        self.bugs = {}

    def load(self, fileobj: typing.IO) -> None:
        """Load database from open JSON file."""
        data = json.load(fileobj)
        try:
            kv = data['kuroneko-version']
            if not isinstance(kv, str):
                raise ValueError()
            major, minor = (int(x) for x in kv.split('.', 1))
        except KeyError:
            raise DatabaseError('No kuroneko-version in database file')
        except ValueError:
            raise DatabaseError('Incorrect kuroneko-version value')
        if major != self.SCHEMA_VERSION[0]:
            raise DatabaseError(f'Incompatible database schema {major}.'
                                f'{minor} ({self.SCHEMA_VERSION} is '
                                f'the current version')

        self.bugs = {}
        for bug in data['bugs']:
            self.bugs[bug['bug']] = Bug(**bug)

    def save(self, fileobj: typing.IO) -> None:
        """Save database into open JSON file."""
        json.dump({
            'kuroneko-version': '.'.join(str(x)
                                         for x in self.SCHEMA_VERSION),
            'bugs': list(x._asdict() for x in self.bugs.values()),
            }, fileobj)

    def add_bug(self,
                bug: int,
                packages: typing.List[typing.List[str]],
                summary: str,
                severity: str,
                created: str,
                resolved: bool,
                ) -> None:
        """Add a new bug to the database."""
        self.bugs[bug] = Bug(
            bug=bug,
            packages=packages,
            summary=summary,
            severity=severity,
            created=created,
            resolved=resolved,
            )


import sys
import telnetlib
import psutil
import signal
import binascii
import regex as re
import OogaAPI as oob
from termcolor import colored
from time import sleep
from os import path

# Config
tn_host = "127.0.0.1" # CSGO telnet stuffs
tn_port = "2121"
cfg_path = "C:\\Program Files (x86)\\Steam\\steamapps\\common\\Counter-Strike Global Offensive\\csgo\\cfg\\" # Path to CSGO config goes here
user = "Example" # Your CSGO Username to avoid infinite looping (just the base name, no clan or anything else)

def signal_handler(signal, frame):
	print("\nquitting...")
	sys.exit(0)

# List PIDs of processes matching processName
def processExists(processName):
	procList = []
	for proc in psutil.process_iter(['name']):
		if proc.info['name'].lower() == processName.lower():
			return True
	return False

# Runs commands on the CS:GO console
def run(txn, command):
	cmd_s = command + "\n"
	txn.write(cmd_s.encode('utf-8'))
	sleep(0.005)

signal.signal(signal.SIGINT, signal_handler)

def main():
	awaiting_user_message = False
	reply_status = True #If bot replies to enemy and teammate messages (true = it does)
	infinite_chat_mode = False #If bot replies to itself (true = it replies)

	if (len(sys.argv) > 1):
		if (sys.argv[1] == "-h" or sys.argv[1] == "--help"):
			print(colored("Run with no arguments to initiate and connect to csgo", attrs=['bold']))
			print(colored("Make sure you set up csgo to receive connections with this launch option: -netconport "+str(tn_port), attrs=['bold']))

	# Make sure CS:GO is running before trying to connect
	if not processExists("csgo.exe"):
		print("Waiting for csgo to start... ")
		while not processExists("csgo.exe"):
			sleep(0.25)
		sleep(10)

	# Initialises CS:GO telnet connection
	print("Trying to connect to " + tn_host + ":" + tn_port)
	try:
		tn = telnetlib.Telnet(tn_host, tn_port)
	except ConnectionRefusedError:
		sleep(30)
		pass
	try:
		tn = telnetlib.Telnet(tn_host, tn_port)
	except ConnectionRefusedError:
		print("Connection refused. Don't forget to add -netconport " + str(tn_port) + " to launch options.")
		sys.exit(1)
	print("Successfully Connected")

	print("Listening for messages...")
	while True:
		try:
			result = tn.expect([b"\r\n"])
			last_line = result[2].decode("utf-8").splitlines()
			last_line = last_line[len(last_line) - 1]
			# Special characters used to determine what and where chat messages start and end.
			if "" in last_line and "" not in last_line:
				whole_line = last_line
				last_line = last_line.split("")

				# Parses the name
				sender = str(last_line[0])
				sender = sender.replace("(Counter-Terrorist) ", "")
				sender = sender.replace("(Terrorist) ", "")
				sender = sender.replace("*DEAD* ", "")
				sender = sender.replace("*DEAD*", "")
				sender = sender.replace("*SPEC* ", "")
				sender = sender.replace("(Spectator) ", "")

				message = str(last_line[1])
				message = re.sub(r'^.*? : ', '', message)
				message = re.sub(r"^\s+", "", message)

				if message == 'OogaMenu' and sender == user:
					awaiting_user_message = True
					sleep(1)
					run(tn, "say 0 - Toggle ooga replies (currently set to " + str(reply_status) + ")")
					sleep(1)
					run(tn, "say 1 - Toggle infinite chat mode (currently set to " + str(infinite_chat_mode) + ")")
					sleep(1)
					run(tn, "say 2 - Close menu")

				if awaiting_user_message == True and sender == user:
					if message == '0':
						reply_status = not reply_status
						awaiting_user_message = False
						sleep(1)
						run(tn, "say Ooga reply status set to " + str(reply_status))
					if message == '1':
						infinite_chat_mode = not infinite_chat_mode
						awaiting_user_message = False
						sleep(1)
						run(tn, "say Infinite chat mode set to " + str(infinite_chat_mode))
					if message == '2':
						awaiting_user_message = False
						sleep(1)
						run(tn, "say Menu Closed")

				if awaiting_user_message == False and reply_status == True:
					if sender == user and infinite_chat_mode == False:
						if message[:7] == 'prompt:':
							print(sender + " : " + message)
							message = message[7:]
							response = oob.getResponse(message)
							run(tn, "say " + response)
							print("AI : " + response)
						else:
							print(sender + " : " + message)
							pass
					else:
						print(sender + " : " + message)
						response = oob.getResponse(message)
						run(tn, "say " + response)
						print("AI : " + response)
		except Exception as e:
			print("Something went wrong. Make sure -netconport " + str(tn_port) + " is added to launch options.")
			print(e)
			sys.exit(1)

if __name__== "__main__":
  main()


import os
import sys
import json
import copy
import numpy as np
import torch
import torchvision.transforms as transforms
from torch.backends import cudnn
import torch.nn as nn
import torchvision
from PIL import Image
from utils.func import *
from utils.vis import *
from utils.IoU import *
from models.models import choose_locmodel,choose_clsmodel
from utils.augment import *
import argparse
from image_loader import get_bbox_dict
'''
parser = argparse.ArgumentParser(description='Parameters for PSOL evaluation')
parser.add_argument('--loc-model', metavar='locarg', type=str, default='vgg16',dest='locmodel')
parser.add_argument('--cls-model', metavar='clsarg', type=str, default='vgg16',dest='clsmodel')
parser.add_argument('--input_size',default=256,dest='input_size')
parser.add_argument('--crop_size',default=224,dest='crop_size')
parser.add_argument('--ten-crop', help='tencrop', action='store_true',dest='tencrop')
parser.add_argument('--gpu',help='which gpu to use',default='4',dest='gpu')
parser.add_argument('data',metavar='DIR',help='path to imagenet dataset')

args = parser.parse_args()
os.environ['CUDA_VISIBLE_DEVICES'] = args.gpu
os.environ['OMP_NUM_THREADS'] = "4"
os.environ['MKL_NUM_THREADS'] = "4"
'''

def copy_parameters(model, pretrained_dict):
    model_dict = model.state_dict()

    pretrained_dict = {k[7:]: v for k, v in pretrained_dict.items() if k[7:] in model_dict and pretrained_dict[k].size()==model_dict[k[7:]].size()}
    for k, v in pretrained_dict.items():
        print(k)
    model_dict.update(pretrained_dict)
    model.load_state_dict(model_dict)
    return model

def choose_locmodel(model_name, model_path=None, num_classes=1000):#, pretrained=False):
    if model_name == 'densenet161':
        model = torchvision.models.densenet161(pretrained=True)

        model.classifier = nn.Sequential(
            nn.Linear(2208, 512),
            nn.ReLU(),
            nn.Linear(512, 4),
            nn.Sigmoid()
        )
        if model_path:
            model = copy_parameters(model, torch.load(model_path))
    elif model_name == 'resnet50':
        model = torchvision.models.resnet50(pretrained=False, num_classes=num_classes)
        model.fc = nn.Sequential(
            nn.Linear(2048, 512),
            nn.ReLU(),
            nn.Linear(512, 4),
            nn.Sigmoid()
        )
        if model_path:
            model = copy_parameters(model, torch.load(model_path))
    elif model_name == 'vgggap':
        model = VGGGAP(pretrained=True,num_classes=num_classes)
        if model_path:
            model = copy_parameters(model, torch.load(model_path))
    elif model_name == 'vgg16':
        model = VGG16(pretrained=True,num_classes=num_classes)
        if model_path:
            model = copy_parameters(model, torch.load(model_path))
    elif model_name == 'inceptionv3':
        #need for rollback inceptionv3 official code
        pass
    else:
        raise ValueError('Do not have this model currently!')
    return model

def psol_infer(data, locmodel, model_path, input_size=256, crop_size=224, gt=True, visualize=True, visualize_pct=0.01, colab=False):
    cudnn.benchmark = True
    normalize = transforms.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225))
    transform = transforms.Compose([
            transforms.Resize((input_size, input_size)),
            transforms.CenterCrop(crop_size),
            transforms.ToTensor(),
            normalize
    ])
    cls_transform = transforms.Compose([
            transforms.Resize((input_size, input_size)),
            transforms.CenterCrop(crop_size),
            transforms.ToTensor(),
            normalize
    ])
    ten_crop_aug = transforms.Compose([
        transforms.Resize((input_size, input_size)),
        transforms.TenCrop(crop_size),
        transforms.Lambda(lambda crops: torch.stack([transforms.ToTensor()(crop) for crop in crops])),
        transforms.Lambda(lambda crops: torch.stack([normalize(crop) for crop in crops])),
    ])

    root = data
    val_imagedir = os.path.join(root, 'val')
    classes = os.listdir(val_imagedir)
    classes.sort()
    temp_softmax = nn.Softmax()

    locname = locmodel
    model = choose_locmodel(locname, model_path, len(classes))

    print(model)
    model = model.to(0)
    model.eval()
    class_to_idx = {classes[i]:i for i in range(len(classes))}

    savepath = os.path.join(root, 'annoted')
    result = {}

    accs = []
    accs_top5 = []
    ious = []
    cls_accs = []
    final_cls = []
    final_iou = []
    final_clsloc = []
    final_clsloctop5 = []
    final_ind = []
    for k in range(len(classes)):
        cls = classes[k]

        total = 0
        IoUSet = []
        IoUSetTop5 = []
        LocSet = []
        ClsSet = []

        files = os.listdir(os.path.join(val_imagedir, cls))
        files.sort()
        if gt:
            gt_dict = get_bbox_dict(root)
        for (i, name) in enumerate(files):
            # raw_img = cv2.imread(os.path.join(imagedir, cls, name))
            '''
            now_index = int(name.split('_')[-1].split('.')[0])
            final_ind.append(now_index-1)
            xmlfile = os.path.join(val_annodir, cls, name.split('.')[0] + '.xml')
            '''
            if gt:
                gt_bbox = gt_dict[os.path.join(cls, name)]

            raw_img = Image.open(os.path.join(val_imagedir, cls, name)).convert('RGB')

            with torch.no_grad():
                img = transform(raw_img)
                img = torch.unsqueeze(img, 0)
                img = img.to(0)
                reg_outputs = model(img)

                bbox = to_data(reg_outputs)
                bbox = torch.squeeze(bbox)
                bbox = bbox.numpy()
            w, h = crop_size, crop_size
            bbox[0] = bbox[0] * w
            bbox[2] = bbox[2] * w + bbox[0]
            bbox[1] = bbox[1] * h
            bbox[3] = bbox[3] * h + bbox[1]
            #handle resize and centercrop for gt_boxes
            #for j in range(len(gt_boxes)):
            if gt:
                temp_list = list(gt_bbox)
                raw_img_i, gt_bbox_i = ResizedBBoxCrop((input_size, input_size))(raw_img, temp_list)
                raw_img_i, gt_bbox_i = CenterBBoxCrop((crop_size))(raw_img_i, gt_bbox_i)
                w, h = raw_img_i.size

                gt_bbox_i[0] = gt_bbox_i[0] * w
                gt_bbox_i[2] = gt_bbox_i[2] * w
                gt_bbox_i[1] = gt_bbox_i[1] * h
                gt_bbox_i[3] = gt_bbox_i[3] * h

                #raw_img = raw_img_i
                gt_box = gt_bbox_i
                iou = IoU(bbox, gt_box)
                LocSet.append(iou)

                result[os.path.join(cls, name)] = iou
                IoUSet.append(iou)
            else:
                raw_img_i = raw_img

            #visualization code
            if visualize:
                opencv_image = copy.deepcopy(np.array(raw_img_i))
                opencv_image = opencv_image[:, :, ::-1].copy()
                if gt:
                    cv2.rectangle(opencv_image, (int(gt_box[0]), int(gt_box[1])),
                        (int(gt_box[2]), int(gt_box[3])), (0, 255, 0), 4)
                cv2.rectangle(opencv_image, (bbox[0], bbox[1]), (bbox[2], bbox[3]),
                              (0, 255, 255), 4)
                if np.random.binomial(1, visualize_pct, 1):
                    if colab:
                        from google.colab.patches import cv2_imshow
                        cv2_imshow(opencv_image)
                    else:
                        cv2.imshow(opencv_image)
                cv2.imwrite(os.path.join(savepath, str(name) + '.jpg'), np.asarray(opencv_image))

        if gt:
            cls_loc_acc = np.sum(np.array(IoUSet) > 0.5) / len(IoUSet)
            final_clsloc.extend(IoUSet)
            iou_avg = np.sum(np.array(IoUSet)) / len(IoUSet)
            #final_iou.extend(LocSet)

            print('{} cls-loc acc is {}, avg iou is {}'.format(cls, cls_loc_acc, iou_avg))
            with open('inference_CorLoc.txt', 'a+') as corloc_f:
                corloc_f.write('{} {}\n'.format(cls, iou_avg))
            accs.append(cls_loc_acc)
            ious.append(iou_avg)
            if (k+1) %100==0:
                print(k)

    if gt:
        print(accs)
        print('Cls-Loc acc {}'.format(np.mean(accs)))

        print('Avg IoU {}'.format(np.mean(ious)))
        #with open('Corloc_result.txt', 'w') as f:
         #   for k in sorted(result.keys()):
          #      f.write('{} {}\n'.format(k, str(result[k])))


from azure.mgmt.cdn.models import (ForwardingProtocol, AfdQueryStringCachingBehavior, SkuName)
from azure.cli.core.aaz._base import has_value
from azure.cli.core.commands.client_factory import get_subscription_id
from azure.cli.core.azclierror import InvalidArgumentValueError
from azure.core.exceptions import ResourceNotFoundError
from azure.cli.command_modules.cdn.aaz.latest.afd.custom_domain import Create as _AFDCustomDomainCreate, \
    Update as _AFDCustomDomainUpdate
from azure.cli.command_modules.cdn.aaz.latest.afd.origin import Create as _AFDOriginCreate, Update as _AFDOriginUpdate
from azure.cli.command_modules.cdn.aaz.latest.afd.route import Show as _AFDRouteShow, \
    Create as _AFDRouteCreate, Update as _AFDRouteUpdate
from azure.cli.command_modules.cdn.aaz.latest.afd.rule import Show as _RuleShow, \
    Create as _AFDRuleCreate, Update as _AFDRuleUpdate
from azure.cli.command_modules.cdn.aaz.latest.afd.secret import Show as _AFDSecretShow, \
    Create as _AFDSecretCreate, Update as _AFDSecretUpdate
from azure.cli.command_modules.cdn.aaz.latest.afd.security_policy import Show as _AFDSecurityPolicyShow, \
    Create as _AFDSecurityPolicyCreate, Update as _AFDSecurityPolicyUpdate
from azure.cli.command_modules.cdn.aaz.latest.afd.profile import Show as _AFDProfileShow, \
    Create as _AFDProfileCreate, Update as _AFDProfileUpdate
from azure.cli.command_modules.cdn.aaz.latest.afd.endpoint import Show as _AFDEndpointShow, \
    Create as _AFDEndpointCreate, Update as _AFDEndpointUpdate
from azure.cli.core.aaz import AAZStrArg, AAZBoolArg, AAZListArg, AAZDateArg
from knack.log import get_logger
from .custom_rule_util import (create_condition, create_action,
                               create_conditions_from_existing, create_actions_from_existing)
logger = get_logger(__name__)

def default_content_types():
    return ['application/eot',
            'application/font',
            'application/font-sfnt',
            'application/javascript',
            'application/json',
            'application/opentype',
            'application/otf',
            'application/pkcs7-mime',
            'application/truetype',
            'application/ttf',
            'application/vnd.ms-fontobject',
            'application/xhtml+xml',
            'application/xml',
            'application/xml+rss',
            'application/x-font-opentype',
            'application/x-font-truetype',
            'application/x-font-ttf',
            'application/x-httpd-cgi',
            'application/x-javascript',
            'application/x-mpegurl',
            'application/x-opentype',
            'application/x-otf',
            'application/x-perl',
            'application/x-ttf',
            'font/eot',
            'font/ttf',
            'font/otf',
            'font/opentype',
            'image/svg+xml',
            'text/css',
            'text/csv',
            'text/html',
            'text/javascript',
            'text/js',
            'text/plain',
            'text/richtext',
            'text/tab-separated-values',
            'text/xml',
            'text/x-script',
            'text/x-component',
            'text/x-java-source']

class AFDCustomDomainCreate(_AFDCustomDomainCreate):
    @classmethod
    def _build_arguments_schema(cls, *args, **kwargs):
        args_schema = super()._build_arguments_schema(*args, **kwargs)
        return args_schema

    def pre_operations(self):
        args = self.ctx.args
        if has_value(args.azure_dns_zone) and "/dnszones/" not in args.azure_dns_zone.to_serialized_data().lower():
            raise InvalidArgumentValueError('azure_dns_zone should be valid Azure dns zone ID.')
        if has_value(args.secret) and "/secrets/" not in args.secret.to_serialized_data().lower():
            args.secret = f'/subscriptions/{self.ctx.subscription_id}/resourceGroups/{args.resource_group}' \
                          f'/providers/Microsoft.Cdn/profiles/{args.profile_name}/secrets/{args.secret}'

class AFDCustomDomainUpdate(_AFDCustomDomainUpdate):
    @classmethod
    def _build_arguments_schema(cls, *args, **kwargs):
        args_schema = super()._build_arguments_schema(*args, **kwargs)
        return args_schema

    def pre_operations(self):
        args = self.ctx.args
        if has_value(args.azure_dns_zone) and "/dnszones/" not in args.azure_dns_zone.to_serialized_data().lower():
            raise InvalidArgumentValueError('azure_dns_zone should be valid Azure dns zone ID.')
        if has_value(args.secret) and "/secrets/" not in args.secret.to_serialized_data().lower():
            args.secret = f'/subscriptions/{self.ctx.subscription_id}/resourceGroups/{args.resource_group}' \
                          f'/providers/Microsoft.Cdn/profiles/{args.profile_name}/secrets/{args.secret}'

class AFDProfileShow(_AFDProfileShow):
    @classmethod
    def _build_arguments_schema(cls, *args, **kwargs):
        args_schema = super()._build_arguments_schema(*args, **kwargs)
        return args_schema

    def _output(self, *args, **kwargs):
        existing = self.deserialize_output(self.ctx.vars.instance, client_flatten=True)
        if existing['sku']['name'] not in (SkuName.premium_azure_front_door, SkuName.standard_azure_front_door):
            logger.warning('Unexpected SKU type, only Standard_AzureFrontDoor and Premium_AzureFrontDoor are supported')
            raise ResourceNotFoundError("Operation returned an invalid status code 'Not Found'")
        return existing

class AFDProfileCreate(_AFDProfileCreate):
    @classmethod
    def _build_arguments_schema(cls, *args, **kwargs):
        args_schema = super()._build_arguments_schema(*args, **kwargs)
        args_schema.location._registered = False
        return args_schema

    def pre_operations(self):
        args = self.ctx.args
        args.location = 'global'

class AFDProfileUpdate(_AFDProfileUpdate):
    @classmethod
    def _build_arguments_schema(cls, *args, **kwargs):
        args_schema = super()._build_arguments_schema(*args, **kwargs)
        args_schema.location._registered = False
        args_schema.sku._registered = False
        return args_schema

    def pre_operations(self):
        args = self.ctx.args
        existing = _AFDProfileShow(cli_ctx=self.cli_ctx)(command_args={
            'resource_group': args.resource_group,
            'profile_name': args.profile_name
        })
        if existing['sku']['name'] not in (SkuName.premium_azure_front_door, SkuName.standard_azure_front_door):
            logger.warning('Unexpected SKU type, only Standard_AzureFrontDoor and Premium_AzureFrontDoor are supported')
            raise ResourceNotFoundError("Operation returned an invalid status code 'Not Found'")
        existing_location = None if 'location' not in existing else existing['location']
        args.location = existing_location

class AFDEndpointCreate(_AFDEndpointCreate):
    @classmethod
    def _build_arguments_schema(cls, *args, **kwargs):
        args_schema = super()._build_arguments_schema(*args, **kwargs)
        args_schema.location._registered = False
        return args_schema

    def pre_operations(self):
        args = self.ctx.args
        args.location = 'global'

class AFDEndpointUpdate(_AFDEndpointUpdate):
    @classmethod
    def _build_arguments_schema(cls, *args, **kwargs):
        args_schema = super()._build_arguments_schema(*args, **kwargs)
        args_schema.location._registered = False
        args_schema.name_reuse_scope._registered = False
        return args_schema

    def pre_operations(self):
        args = self.ctx.args
        existing = _AFDEndpointShow(cli_ctx=self.cli_ctx)(command_args={
            'resource_group': args.resource_group,
            'profile_name': args.profile_name,
            'endpoint_name': args.endpoint_name
        })
        existing_location = None if 'location' not in existing else existing['location']
        args.location = existing_location

class AFDOriginCreate(_AFDOriginCreate):
    @classmethod
    def _build_arguments_schema(cls, *args, **kwargs):
        args_schema = super()._build_arguments_schema(*args, **kwargs)
        args_schema.enable_private_link = AAZBoolArg(
            options=['--enable-private-link'],
            help='Indicates whether private link is enanbled on that origin.',
        )
        args_schema.private_link_location = AAZStrArg(
            options=['--private-link-location'],
            help='The location of origin that will be connected to using the private link.',
        )
        args_schema.private_link_resource = AAZStrArg(
            options=['--private-link-resource'],
            help='The resource ID of the origin that will be connected to using the private link.',
        )
        args_schema.private_link_request_message = AAZStrArg(
            options=['--private-link-request-message'],
            help='The message that is shown to the approver of the private link request.',
        )
        args_schema.private_link_sub_resource_type = AAZStrArg(
            options=['--private-link-sub-resource-type'],
            help='The sub-resource type of the origin that will be connected to using the private '
            'link.You can use "az network private-link-resource list" to obtain the supported sub-resource types.',
        )
        args_schema.shared_private_link_resource._registered = False
        return args_schema

    def pre_operations(self):
        args = self.ctx.args
        shared_private_link_resource = None
        if has_value(args.enable_private_link) and args.enable_private_link.to_serialized_data() is True:
            shared_private_link_resource = {
                'private_link_location': args.private_link_location,
                'private_link': {'id': args.private_link_resource},
                'request_message': args.private_link_request_message,
                'group_id': args.private_link_sub_resource_type
            }
        args.shared_private_link_resource = shared_private_link_resource

class AFDOriginUpdate(_AFDOriginUpdate):
    @classmethod
    def _build_arguments_schema(cls, *args, **kwargs):
        args_schema = super()._build_arguments_schema(*args, **kwargs)
        args_schema.enable_private_link = AAZBoolArg(
            options=['--enable-private-link'],
            help='Indicates whether private link is enanbled on that origin.',
        )
        args_schema.private_link_location = AAZStrArg(
            options=['--private-link-location'],
            help='The location of origin that will be connected to using the private link.',
        )
        args_schema.private_link_resource = AAZStrArg(
            options=['--private-link-resource'],
            help='The resource ID of the origin that will be connected to using the private link.',
        )
        args_schema.private_link_request_message = AAZStrArg(
            options=['--private-link-request-message'],
            help='The message that is shown to the approver of the private link request.',
        )
        args_schema.private_link_sub_resource_type = AAZStrArg(
            options=['--private-link-sub-resource-type'],
            help='The sub-resource type of the origin that will be connected to using the private link.'
            'You can use "az network private-link-resource list" to obtain the supported sub-resource types.',
        )
        args_schema.shared_private_link_resource._registered = False
        return args_schema

    def pre_operations(self):
        args = self.ctx.args
        from azure.cli.command_modules.cdn.aaz.latest.afd.origin import Show
        existing = Show(cli_ctx=self.cli_ctx)(command_args={
            'resource_group': args.resource_group,
            'profile_name': args.profile_name,
            'origin_group_name': args.origin_group_name,
            'origin_name': args.origin_name
        })

        shared_private_link_resource = None
        # if no enable_private_link is specified and origin doesn't have private link resource, then no change
        if (not has_value(args.enable_private_link) and 'sharedPrivateLinkResource' not in existing) or \
                (has_value(args.enable_private_link) and args.enable_private_link.to_serialized_data() is False):
            shared_private_link_resource = None
        # if any private link related parameter is specified, then update the private link resource
        elif ((has_value(args.private_link_location) or
              has_value(args.private_link_resource) or
              has_value(args.private_link_request_message) or
              has_value(args.private_link_sub_resource_type)) or
              args.enable_private_link.to_serialized_data() is True or
              'sharedPrivateLinkResource' in existing):
            # no specified private link related parameter, then use existing private link resource
            existing_private_link_location = None if 'sharedPrivateLinkResource' not in existing or \
                'privateLinkLocation' not in existing['sharedPrivateLinkResource'] \
                else existing['sharedPrivateLinkResource']['privateLinkLocation']
            existing_private_link_resource = None if 'sharedPrivateLinkResource' not in existing or \
                'privateLink' not in existing['sharedPrivateLinkResource'] \
                else existing['sharedPrivateLinkResource']['privateLink']['id']
            existing_private_link_request_message = None if 'sharedPrivateLinkResource' not in existing \
                or 'requestMessage' not in existing['sharedPrivateLinkResource'] else \
                existing['sharedPrivateLinkResource']['requestMessage']
            existing_private_link_sub_resource_type = None if 'sharedPrivateLinkResource' not in existing \
                or 'groupId' not in existing['sharedPrivateLinkResource'] else \
                existing['sharedPrivateLinkResource']['groupId']
            shared_private_link_resource = {
                'private_link_location': args.private_link_location if has_value(args.private_link_location)
                else existing_private_link_location,
                'private_link': {
                    'id': args.private_link_resource if has_value(args.private_link_resource)
                    else existing_private_link_resource
                },
                'request_message': args.private_link_request_message if has_value(args.private_link_request_message)
                else existing_private_link_request_message,
                'group_id': args.private_link_sub_resource_type if has_value(args.private_link_sub_resource_type)
                else existing_private_link_sub_resource_type
            }

        args.shared_private_link_resource = shared_private_link_resource
        args.host_name = args.host_name if args.host_name is not None else existing['hostName']
        args.http_port = args.http_port if args.http_port is not None else existing['httpPort']
        args.https_port = args.https_port if args.https_port is not None else existing['httpsPort']
        args.origin_host_header = args.origin_host_header if args.origin_host_header is not None \
            else existing['originHostHeader']
        args.priority = args.priority if args.priority is not None else existing['priority']
        args.weight = args.weight if args.weight is not None else existing['weight']
        args.enabled_state = args.enabled_state if args.enabled_state is not None else existing['enabledState']
        args.enforce_certificate_name_check = \
            args.enforce_certificate_name_check if args.enforce_certificate_name_check is not None \
            else existing['enforceCertificateNameCheck']

class AFDRouteCreate(_AFDRouteCreate):
    @classmethod
    def _build_arguments_schema(cls, *args, **kwargs):
        args_schema = super()._build_arguments_schema(*args, **kwargs)
        args_schema.enable_caching = AAZBoolArg(
            options=['--enable-caching'],
            help='Indicates whether caching is enanbled on that route.',
        )
        args_schema.custom_domains = AAZListArg(
            options=['--custom-domains'],
            help='Custom domains referenced by this endpoint.',
            nullable=True,
        )
        args_schema.custom_domains.Element = AAZStrArg()
        args_schema.rule_sets = AAZListArg(
            options=['--rule-sets'],
            help='Collection of ID or name of rule set referenced by the route.',
            nullable=True,
        )
        args_schema.rule_sets.Element = AAZStrArg()
        args_schema.query_string_caching_behavior = AAZStrArg(
            options=['--query-string-caching-behavior'],
            help='Defines how Frontdoor caches requests that include query strings.'
            'You can ignore any query strings when caching, ignore specific query strings,'
            'cache every request with a unique URL, or cache specific query strings',
        )
        args_schema.query_parameters = AAZListArg(
            options=['--query-parameters'],
            help='Query parameters to include or exclude.',
        )
        args_schema.query_parameters.Element = AAZStrArg()
        args_schema.content_types_to_compress = AAZListArg(
            options=['--content-types-to-compress'],
            help='List of content types on which compression applies.',
        )
        args_schema.content_types_to_compress.Element = AAZStrArg()
        args_schema.enable_compression = AAZBoolArg(
            options=['--enable-compression'],
            help='Indicates whether content compression is enabled on AzureFrontDoor. '
            'Default value is false. If compression is enabled,'
            'content will be served as compressed if user requests for a compressed version.'
            'Content won\'t be compressed on AzureFrontDoor'
            'when requested content is smaller than 1 byte or larger than 1 MB.',
        )
        args_schema.cache_configuration._registered = False
        args_schema.formatted_custom_domains._registered = False
        args_schema.formatted_rule_sets._registered = False
        return args_schema

    def pre_operations(self):
        args = self.ctx.args

        custom_domains = []
        if has_value(args.custom_domains):
            for custom_domain in args.custom_domains:
                if '/customdomains/' not in custom_domain.to_serialized_data().lower():
                    custom_domain = f'/subscriptions/{self.ctx.subscription_id}/resourceGroups/{args.resource_group}' \
                        f'/providers/Microsoft.Cdn/profiles/{args.profile_name}/customDomains/{custom_domain}'
                    item = {
                        'id': custom_domain,
                    }
                    custom_domains.append(item)
            args.formatted_custom_domains = custom_domains

        if has_value(args.origin_group) and '/origingroups/' not in args.origin_group.to_serialized_data().lower():
            args.origin_group = f'/subscriptions/{self.ctx.subscription_id}/resourceGroups/{args.resource_group}' \
                f'/providers/Microsoft.Cdn/profiles/{args.profile_name}/originGroups/{args.origin_group}'

        cache_configuration = {
            'query_string_caching_behavior': args.query_string_caching_behavior,
            'query_parameters': None if (not has_value(args.query_parameters) or
                                         args.query_parameters is None)
            else ",".join(args.query_parameters.to_serialized_data()),
            'compression_settings': {
                'is_compression_enabled': args.enable_compression,
                'content_types_to_compress': args.content_types_to_compress
            }
        }
        if not has_value(args.enable_caching) or args.enable_caching.to_serialized_data() is False:
            cache_configuration = None
        else:
            if args.cache_configuration is None:
                cache_configuration['compression_settings']['content_types_to_compress'] = default_content_types()
            else:
                cache_configuration['compression_settings']['content_types_to_compress'] = []

        args.cache_configuration = cache_configuration

        rule_sets = []
        if has_value(args.rule_sets):
            for rule_set in args.rule_sets:
                if '/rulesets/' not in rule_set.to_serialized_data().lower():
                    rule_set = f'/subscriptions/{self.ctx.subscription_id}/resourceGroups/{args.resource_group}' \
                        f'/providers/Microsoft.Cdn/profiles/{args.profile_name}/ruleSets/{rule_set}'
                    item = {
                        'id': rule_set,
                    }
                    rule_sets.append(item)
            args.formatted_rule_sets = rule_sets

class AFDRouteUpdate(_AFDRouteUpdate):
    @classmethod
    def _build_arguments_schema(cls, *args, **kwargs):
        args_schema = super()._build_arguments_schema(*args, **kwargs)
        args_schema.enable_caching = AAZBoolArg(
            options=['--enable-caching'],
            help='Indicates whether caching is enanbled on that route.',
        )
        args_schema.custom_domains = AAZListArg(
            options=['--custom-domains'],
            help='Custom domains referenced by this endpoint.',
            nullable=True,
        )
        args_schema.custom_domains.Element = AAZStrArg()
        args_schema.rule_sets = AAZListArg(
            options=['--rule-sets'],
            help='Collection of ID or name of rule set referenced by the route.',
            nullable=True,
        )
        args_schema.rule_sets.Element = AAZStrArg()
        args_schema.query_string_caching_behavior = AAZStrArg(
            options=['--query-string-caching-behavior'],
            help='Defines how Frontdoor caches requests that include query strings.'
            'You can ignore any query strings when caching, ignore specific query strings,'
            'cache every request with a unique URL, or cache specific query strings',
        )
        args_schema.query_parameters = AAZListArg(
            options=['--query-parameters'],
            help='Query parameters to include or exclude.',
        )
        args_schema.query_parameters.Element = AAZStrArg()
        args_schema.content_types_to_compress = AAZListArg(
            options=['--content-types-to-compress'],
            help='List of content types on which compression applies.',
        )
        args_schema.content_types_to_compress.Element = AAZStrArg()
        args_schema.enable_compression = AAZBoolArg(
            options=['--enable-compression'],
            help='Indicates whether content compression is enabled on AzureFrontDoor. Default value is false.'
            'If compression is enabled, content will be served as compressed if user requests for a compressed version.'
            'Content won\'t be compressed on AzureFrontDoor'
            'when requested content is smaller than 1 byte or larger than 1 MB.',
        )
        args_schema.cache_configuration._registered = False
        args_schema.formatted_custom_domains._registered = False
        args_schema.formatted_rule_sets._registered = False
        return args_schema

    def pre_operations(self):
        args = self.ctx.args

        custom_domains = []
        if has_value(args.custom_domains):
            for custom_domain in args.custom_domains:
                if '/customdomains/' not in custom_domain.to_serialized_data().lower():
                    custom_domain = f'/subscriptions/{self.ctx.subscription_id}/resourceGroups/{args.resource_group}' \
                        f'/providers/Microsoft.Cdn/profiles/{args.profile_name}/customDomains/{custom_domain}'
                    item = {
                        'id': custom_domain,
                    }
                    custom_domains.append(item)
            args.formatted_custom_domains = custom_domains

        if has_value(args.origin_group) and '/origingroups/' not in args.origin_group.to_serialized_data().lower():
            args.origin_group = f'/subscriptions/{self.ctx.subscription_id}/resourceGroups/{args.resource_group}' \
                f'/providers/Microsoft.Cdn/profiles/{args.profile_name}/originGroups/{args.origin_group}'

        existing = _AFDRouteShow(cli_ctx=self.cli_ctx)(command_args={
            'resource_group': args.resource_group,
            'profile_name': args.profile_name,
            'endpoint_name': args.endpoint_name,
            'route_name': args.route_name
        })

        cache_configuration = {
            'query_string_caching_behavior': args.query_string_caching_behavior,
            'query_parameters': None if (not has_value(args.query_parameters) or
                                         args.query_parameters is None)
            else ",".join(args.query_parameters.to_serialized_data()),
            'compression_settings': {
                'is_compression_enabled': args.enable_compression,
                'content_types_to_compress': args.content_types_to_compress,
            }
        }

        # if not specified, then use existing cache configuration
        if not has_value(args.enable_caching):
            if 'cacheConfiguration' not in existing or existing['cacheConfiguration'] is None:
                cache_configuration = None
            else:
                # if already has cache configuration, then use existing cache configuration
                if not has_value(args.query_string_caching_behavior):
                    if ('cacheConfiguration' in existing and
                            'queryStringCachingBehavior' in existing['cacheConfiguration']):
                        cache_configuration['query_string_caching_behavior'] = \
                            existing['cacheConfiguration']['queryStringCachingBehavior']
                if not has_value(args.query_parameters):
                    if 'cacheConfiguration' in existing and 'queryParameters' in existing['cacheConfiguration']:
                        cache_configuration['query_parameters'] = existing['cacheConfiguration']['queryParameters']
                if not has_value(args.content_types_to_compress):
                    if ('cacheConfiguration' in existing and
                            'compressionSettings' in existing['cacheConfiguration'] and
                            'contentTypesToCompress' in existing['cacheConfiguration']['compressionSettings']):
                        cache_configuration['compression_settings']['content_types_to_compress'] = \
                            existing['cacheConfiguration']['compressionSettings']['contentTypesToCompress']
                if not has_value(args.enable_compression):
                    if ('cacheConfiguration' in existing and
                            'compressionSettings' in existing['cacheConfiguration'] and
                            'isCompressionEnabled' in existing['cacheConfiguration']['compressionSettings']):
                        cache_configuration['compression_settings']['is_compression_enabled'] = \
                            existing['cacheConfiguration']['compressionSettings']['isCompressionEnabled']
        elif args.enable_caching.to_serialized_data() is False:
            cache_configuration = None
        # if caching setting specified and set to true, check compression setting
        else:
            # if not specified, then use existing compression settings
            if (not has_value(args.enable_compression) and 'cacheConfiguration' in existing and
                    'compressionSettings' in existing['cacheConfiguration'] and
                    'contentTypesToCompress' in existing['cacheConfiguration']['compressionSettings']):
                cache_configuration['compression_settings']['content_types_to_compress'] = \
                    existing['cacheConfiguration']['compressionSettings']['contentTypesToCompress']
            elif args.enable_compression.to_serialized_data() is False:
                cache_configuration['compression_settings']['content_types_to_compress'] = []
            else:
                # if compression setting specified and set to true, check content types to compress
                if (not has_value(args.content_types_to_compress) or
                        args.content_types_to_compress.to_serialized_data() is None):
                    cache_configuration['compression_settings']['content_types_to_compress'] = default_content_types()
        args.cache_configuration = cache_configuration

        rule_sets = []
        if has_value(args.rule_sets):
            for rule_set in args.rule_sets:
                if '/rulesets/' not in rule_set.to_serialized_data().lower():
                    rule_set = f'/subscriptions/{self.ctx.subscription_id}/resourceGroups/{args.resource_group}' \
                        f'/providers/Microsoft.Cdn/profiles/{args.profile_name}/ruleSets/{rule_set}'
                    item = {
                        'id': rule_set,
                    }
                    rule_sets.append(item)
            args.formatted_rule_sets = rule_sets

class AFDRuleCreate(_AFDRuleCreate):
    @classmethod
    def _build_arguments_schema(cls, *args, **kwargs):
        args_schema = super()._build_arguments_schema(*args, **kwargs)
        args_schema.action_name = AAZStrArg(
            options=['--action-name'],
            help='The name of the action for the delivery rule: '
            'https://docs.microsoft.com/en-us/azure/frontdoor/front-door-rules-engine-actions.',
        )
        args_schema.cache_behavior = AAZStrArg(
            options=['--cache-behavior'],
            help='Caching behavior for the requests.',
        )
        args_schema.cache_duration = AAZDateArg(
            options=['--cache-duration'],
            help='The duration for which the content needs to be cached. Allowed format is [d.]hh:mm:ss.',
        )
        args_schema.custom_fragment = AAZStrArg(
            options=['--custom-fragment'],
            help='Fragment to add to the redirect URL.',
        )
        args_schema.custom_hostname = AAZStrArg(
            options=['--custom-hostname'],
            help='Host to redirect. Leave empty to use the incoming host as the destination host.',
        )
        args_schema.custom_path = AAZStrArg(
            options=['--custom-path'],
            help='The full path to redirect. Path cannot be empty and must start with /.'
            'Leave empty to use the incoming path as destination pat',
        )
        args_schema.custom_querystring = AAZStrArg(
            options=['--custom-querystring'],
            help='The set of query strings to be placed in the redirect URL.'
            'leave empty to preserve the incoming query string.',
        )
        args_schema.destination = AAZStrArg(
            options=['--destination'],
            help='The destination path to be used in the rewrite.',
        )
        args_schema.enable_caching = AAZBoolArg(
            options=['--enable-caching'],
            help='Indicates whether to enable caching on the route.',
        )
        args_schema.enable_compression = AAZBoolArg(
            options=['--enable-compression'],
            help='Indicates whether content compression is enabled on AzureFrontDoor. Default value is false.'
            'If compression is enabled, content will be served as compressed if user requests for a compressed version.'
            'Content won\'t be compressed on AzureFrontDoor'
            'when requested content is smaller than 1 byte or larger than 1 MB.',
        )
        args_schema.forwarding_protocol = AAZStrArg(
            options=['--forwarding-protocol'],
            help='Protocol this rule will use when forwarding traffic to backends.',
        )
        args_schema.header_action = AAZStrArg(
            options=['--header-action'],
            help='Header action for the requests.'
        )
        args_schema.header_name = AAZStrArg(
            options=['--header-name'],
            help='Name of the header to modify.'
        )
        args_schema.header_value = AAZStrArg(
            options=['--header-value'],
            help='Value of the header.',
        )
        args_schema.match_values = AAZListArg(
            options=['--match-values'],
            help='Match values of the match condition. e.g, space separated values \'GET\' \'HTTP\'.',
        )
        args_schema.match_values.Element = AAZStrArg()
        args_schema.match_variable = AAZStrArg(
            options=['--match-variable'],
            help='Name of the match condition: '
            'https://docs.microsoft.com/en-us/azure/frontdoor/rules-match-conditions.',
        )
        args_schema.negate_condition = AAZBoolArg(
            options=['--negate-condition'],
            help='If true, negates the condition.',
        )
        args_schema.operator = AAZStrArg(
            options=['--operator'],
            help='Operator of the match condition.',
        )
        args_schema.origin_group = AAZStrArg(
            options=['--origin-group'],
            help='Name or ID of the OriginGroup that would override the default OriginGroup.',
        )
        args_schema.preserve_unmatched_path = AAZBoolArg(
            options=['--preserve-unmatched-path'],
            help='If True, the remaining path after the source pattern will be appended to the new destination path.',
        )
        args_schema.query_parameters = AAZListArg(
            options=['--query-parameters'],
            help='Query parameters to include or exclude.',
        )
        args_schema.query_parameters.Element = AAZStrArg()
        args_schema.query_string_caching_behavior = AAZStrArg(
            options=['--query-string-caching-behavior'],
            help='Defines how CDN caches requests that include query strings.'
            'You can ignore any query strings when caching,'
            'bypass caching to prevent requests that contain query strings from being cached,'
            'or cache every request with a unique URL.',
        )
        args_schema.redirect_protocol = AAZStrArg(
            options=['--redirect-protocol'],
            help='Protocol to use for the redirect.',
        )
        args_schema.redirect_type = AAZStrArg(
            options=['--redirect-type'],
            help='The redirect type the rule will use when redirecting traffic.',
        )
        args_schema.selector = AAZStrArg(
            options=['--selector'],
            help='Selector of the match condition.',
        )
        args_schema.source_pattern = AAZStrArg(
            options=['--source-pattern'],
            help='A request URI pattern that identifies the type of requests that may be rewritten.',
        )
        args_schema.transforms = AAZListArg(
            options=['--transforms'],
            help='Transform to apply before matching.',
        )
        args_schema.transforms.Element = AAZStrArg()
        args_schema.actions._registered = False
        args_schema.conditions._registered = False
        return args_schema

    def pre_operations(self):
        args = self.ctx.args
        # conditions
        conditions = []
        condition = create_condition(args.match_variable, args.operator,
                                     args.match_values, args.selector, args.negate_condition, args.transforms)
        if condition is not None:
            conditions.append(condition)
        args.conditions = conditions

        # actions
        actions = []
        action = create_action(
            args.action_name, args.cache_behavior, args.cache_duration, args.header_action,
            args.header_name, args.header_value, None,
            None if args.query_parameters is None else ','.join(args.query_parameters),
            args.redirect_type, args.redirect_protocol, args.custom_hostname,
            args.custom_path, args.custom_querystring, args.custom_fragment, args.source_pattern,
            args.destination, args.preserve_unmatched_path,
            origin_group=args.origin_group,
            sub_id=self.ctx.subscription_id,
            enable_caching=args.enable_caching,
            resource_group_name=args.resource_group,
            profile_name=args.profile_name,
            enable_compression=args.enable_compression,
            query_string_caching_behavior=args.query_string_caching_behavior,
            forwarding_protocol=args.forwarding_protocol,
        )
        if action is not None:
            actions.append(action)
        args.actions = actions

def add_afd_rule_condition(cmd, resource_group_name, profile_name, rule_set_name,
                           rule_name, match_variable, operator, match_values=None, selector=None,
                           negate_condition=None, transforms=None):

    existing = _RuleShow(cli_ctx=cmd.cli_ctx)(command_args={
        'resource_group': resource_group_name,
        'profile_name': profile_name,
        'rule_set_name': rule_set_name,
        'rule_name': rule_name
    })
    condition = create_condition(match_variable, operator, match_values, selector, negate_condition, transforms)
    conditions = create_conditions_from_existing(existing['conditions'])
    conditions.append(condition)
    existing_actions = create_actions_from_existing(existing['actions'])

    return _AFDRuleUpdate(cli_ctx=cmd.cli_ctx)(command_args={
        'resource_group': resource_group_name,
        'profile_name': profile_name,
        'rule_set_name': rule_set_name,
        'rule_name': rule_name,
        'conditions': conditions,
        'actions': existing_actions,
        'match_processing_behavior': None
        if 'matchProcessingBehavior' not in existing
        else existing['matchProcessingBehavior'],
        'order': None if 'order' not in existing else existing['order']
    })

def add_afd_rule_action(cmd, resource_group_name, profile_name, rule_set_name,
                        rule_name, action_name, cache_behavior=None, cache_duration=None,
                        header_action=None, header_name=None, header_value=None,
                        query_parameters=None, redirect_type=None, redirect_protocol=None, custom_hostname=None,
                        custom_path=None, custom_querystring=None, custom_fragment=None, source_pattern=None,
                        destination=None, preserve_unmatched_path=None, origin_group=None,
                        forwarding_protocol: ForwardingProtocol = None,
                        query_string_caching_behavior: AfdQueryStringCachingBehavior = None,
                        is_compression_enabled=None,
                        enable_caching=None):
    existing = _RuleShow(cli_ctx=cmd.cli_ctx)(command_args={
        'resource_group': resource_group_name,
        'profile_name': profile_name,
        'rule_set_name': rule_set_name,
        'rule_name': rule_name
    })
    actions = create_actions_from_existing(existing['actions'])
    existing_conditions = create_conditions_from_existing(existing['conditions'])

    action = create_action(action_name, cache_behavior, cache_duration, header_action, header_name,
                           header_value, None, None if query_parameters is None else ','.join(query_parameters),
                           redirect_type, redirect_protocol, custom_hostname, custom_path, custom_querystring,
                           custom_fragment, source_pattern, destination, preserve_unmatched_path,
                           resource_group_name=resource_group_name,
                           forwarding_protocol=forwarding_protocol,
                           origin_group=origin_group, profile_name=profile_name,
                           query_string_caching_behavior=query_string_caching_behavior,
                           enable_compression=is_compression_enabled,
                           enable_caching=enable_caching,
                           sub_id=get_subscription_id(cmd.cli_ctx))
    actions.append(action)

    return _AFDRuleUpdate(cli_ctx=cmd.cli_ctx)(command_args={
        'resource_group': resource_group_name,
        'profile_name': profile_name,
        'rule_set_name': rule_set_name,
        'rule_name': rule_name,
        'conditions': existing_conditions,
        'actions': actions,
        'match_processing_behavior': None
        if 'matchProcessingBehavior' not in existing
        else existing['matchProcessingBehavior'],
        'order': None if 'order' not in existing else existing['order']
    })

def remove_afd_rule_condition(cmd, resource_group_name, profile_name,
                              rule_set_name, rule_name, index):

    existing = _RuleShow(cli_ctx=cmd.cli_ctx)(command_args={
        'resource_group': resource_group_name,
        'profile_name': profile_name,
        'rule_set_name': rule_set_name,
        'rule_name': rule_name
    })
    conditions = create_conditions_from_existing(existing['conditions'])
    existing_actions = create_actions_from_existing(existing['actions'])

    if len(conditions) > 1 and index < len(conditions):
        conditions.pop(index)
    else:
        logger.warning('Invalid condition index found. This command will be skipped. Please check the rule.')

    return _AFDRuleUpdate(cli_ctx=cmd.cli_ctx)(command_args={
        'resource_group': resource_group_name,
        'profile_name': profile_name,
        'rule_set_name': rule_set_name,
        'rule_name': rule_name,
        'conditions': conditions,
        'actions': existing_actions,
        'match_processing_behavior': None
        if 'matchProcessingBehavior' not in existing
        else existing['matchProcessingBehavior'],
        'order': None if 'order' not in existing else existing['order']
    })

def remove_afd_rule_action(cmd, resource_group_name, profile_name, rule_set_name, rule_name, index):

    existing = _RuleShow(cli_ctx=cmd.cli_ctx)(command_args={
        'resource_group': resource_group_name,
        'profile_name': profile_name,
        'rule_set_name': rule_set_name,
        'rule_name': rule_name
    })

    existing_conditions = create_conditions_from_existing(existing['conditions'])
    actions = create_actions_from_existing(existing['actions'])
    if len(actions) > 1 and index < len(actions):
        actions.pop(index)
    else:
        logger.warning('Invalid condition index found. This command will be skipped. Please check the rule.')

    return _AFDRuleUpdate(cli_ctx=cmd.cli_ctx)(command_args={
        'resource_group': resource_group_name,
        'profile_name': profile_name,
        'rule_set_name': rule_set_name,
        'rule_name': rule_name,
        'actions': actions,
        'conditions': existing_conditions,
        'match_processing_behavior': None
        if 'matchProcessingBehavior' not in existing
        else existing['matchProcessingBehavior'],
        'order': None if 'order' not in existing else existing['order']
    })

def list_afd_rule_condition(cmd, resource_group_name,
                            profile_name, rule_set_name,
                            rule_name):
    existing = _RuleShow(cli_ctx=cmd.cli_ctx)(command_args={
        'resource_group': resource_group_name,
        'profile_name': profile_name,
        'rule_set_name': rule_set_name,
        'rule_name': rule_name
    })

    return existing['conditions']

def list_afd_rule_action(cmd, resource_group_name,
                         profile_name, rule_set_name,
                         rule_name):
    existing = _RuleShow(cli_ctx=cmd.cli_ctx)(command_args={
        'resource_group': resource_group_name,
        'profile_name': profile_name,
        'rule_set_name': rule_set_name,
        'rule_name': rule_name
    })

    return existing['actions']

class AFDSecretCreate(_AFDSecretCreate):
    @classmethod
    def _build_arguments_schema(cls, *args, **kwargs):
        args_schema = super()._build_arguments_schema(*args, **kwargs)
        args_schema.secret_source = AAZStrArg(
            options=['--secret-source'],
            help='Resource ID of the Azure Key Vault certificate, expected format is like'
            '/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.KeyVault/vaults/vault1/secrets/cert1.',
            required=True,
        )
        args_schema.secret_version = AAZStrArg(
            options=['--secret-version'],
            help='Version of the certificate to be used.',
        )
        args_schema.use_latest_version = AAZBoolArg(
            options=['--use-latest-version'],
            help='Whether to use the latest version for the certificate.',
        )
        args_schema.parameters._registered = False
        return args_schema

    def pre_operations(self):
        args = self.ctx.args
        if "/secrets/" not in args.secret_source.to_serialized_data().lower():
            raise InvalidArgumentValueError('secret_source should be valid Azure key vault certificate ID.')

        if not has_value(args.secret_version) and not args.use_latest_version.to_serialized_data():
            raise InvalidArgumentValueError('Either specify secret_version or enable use_latest_version.')
        parameters = None
        if has_value(args.use_latest_version) and args.use_latest_version.to_serialized_data() is True:
            parameters = {
                'customer-certificate': {
                    'secret-source': {'id': args.secret_source},
                    'secret-version': None,
                    'use-latest-version': True
                }
            }
        else:
            parameters = {
                'customer-certificate': {
                    'secret-source': {'id': args.secret_source},
                    'secret-version': args.secret_version,
                    'use-latest-version': False
                }
            }
        args.parameters = parameters

class AFDSecretUpdate(_AFDSecretUpdate):
    @classmethod
    def _build_arguments_schema(cls, *args, **kwargs):
        args_schema = super()._build_arguments_schema(*args, **kwargs)
        args_schema.secret_source = AAZStrArg(
            options=['--secret-source'],
            help='Resource ID of the Azure Key Vault certificate, expected format is like'
            '/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.KeyVault/vaults/vault1/secrets/cert1.',
        )
        args_schema.secret_version = AAZStrArg(
            options=['--secret-version'],
            help='Version of the certificate to be used.',
        )
        args_schema.use_latest_version = AAZBoolArg(
            options=['--use-latest-version'],
            help='Whether to use the latest version for the certificate.',
        )
        args_schema.parameters._registered = False
        return args_schema

    def pre_operations(self):
        args = self.ctx.args
        existing = _AFDSecretShow(cli_ctx=self.cli_ctx)(command_args={
            'resource_group': args.resource_group,
            'profile_name': args.profile_name,
            'secret_name': args.secret_name
        })

        para = existing['parameters']
        secret_source = args.secret_source if has_value(args.secret_source) else para['secretSource']['id']
        if 'secretVersion' in para and para['secretVersion'] in args.secret_source.to_serialized_data():
            existing_secret_version = para['secretVersion']
            version_start = args.secret_source.to_serialized_data().lower().rindex(f'/{existing_secret_version}')
            secret_source = args.secret_source.to_serialized_data()[0:version_start]

        secret_version = args.secret_version \
            if has_value(args.secret_version) and args.secret_version is not None \
            else para['secretVersion']
        use_latest_version = args.use_latest_version \
            if has_value(args.use_latest_version) and args.use_latest_version is not None \
            else para['useLatestVersion']

        parameters = {
            'customer-certificate': {
                'secret-source': {'id': secret_source},
                'secret-version': secret_version,
                'use-latest-version': use_latest_version
            }
        }
        args.parameters = parameters

class AFDSecurityPolicyCreate(_AFDSecurityPolicyCreate):
    @classmethod
    def _build_arguments_schema(cls, *args, **kwargs):
        args_schema = super()._build_arguments_schema(*args, **kwargs)
        args_schema.domains = AAZListArg(
            options=['--domains'],
            help='The domains to associate with the WAF policy. Could either be the ID of an endpoint'
            '(default domain will be used in that case) or ID of a custom domain.',
            required=True,
        )
        args_schema.domains.Element = AAZStrArg()
        args_schema.waf_policy = AAZStrArg(
            options=['--waf-policy'],
            help='The ID of Front Door WAF policy.',
            required=True,
        )
        args_schema.web_application_firewall._registered = False
        return args_schema

    def pre_operations(self):
        args = self.ctx.args

        if any(("/afdendpoints/" not in domain.lower() and
                "/customdomains/" not in domain.lower()) for domain in args.domains.to_serialized_data()):
            raise InvalidArgumentValueError('Domain should either be endpoint ID or custom domain ID.')
        if (has_value(args.waf_policy) and
                "/frontdoorwebapplicationfirewallpolicies/" not in args.waf_policy.to_serialized_data().lower()):
            raise InvalidArgumentValueError('waf_policy should be Front Door WAF policy ID.')

        domains = []
        if has_value(args.domains):
            for domain in args.domains:
                domains.append({
                    'id': domain
                })

        associations = [{
            'domains': domains,
            'patterns_to_match': ['/*']
        }]

        args.web_application_firewall = {
            'waf_policy': args.waf_policy,
            'associations': associations
        }

class AFDSecurityPolicyUpdate(_AFDSecurityPolicyUpdate):
    @classmethod
    def _build_arguments_schema(cls, *args, **kwargs):
        args_schema = super()._build_arguments_schema(*args, **kwargs)
        args_schema.domains = AAZListArg(
            options=['--domains'],
            help='The domains to associate with the WAF policy. Could either be the ID of an endpoint'
            '(default domain will be used in that case) or ID of a custom domain.',
        )
        args_schema.domains.Element = AAZStrArg()

        args_schema.waf_policy = AAZStrArg(
            options=['--waf-policy'],
            help='The ID of Front Door WAF policy.',
        )
        args_schema.web_application_firewall._registered = False
        return args_schema

    def pre_operations(self):
        args = self.ctx.args
        existing_security_policy = _AFDSecurityPolicyShow(cli_ctx=self.cli_ctx)(command_args={
            'resource_group': args.resource_group,
            'profile_name': args.profile_name,
            'security_policy_name': args.security_policy_name
        })

        associations = existing_security_policy['parameters']['associations']

        domains = []
        if has_value(args.domains):
            for domain in args.domains:
                domains.append({
                    'id': domain
                })
            associations = [{
                'domains': domains,
                'patterns_to_match': ['/*'],
            }]

        args.web_application_firewall = {
            'waf_policy': args.waf_policy if has_value(args.waf_policy)
            else existing_security_policy['parameters']['wafPolicy'],
            'associations': associations
        }